@factorialco/f0-react-native 0.19.1
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 +54 -0
- package/package.json +84 -0
- package/src/components/Activity/ActivityItem/__snapshots__/index.spec.tsx.snap +62 -0
- package/src/components/Activity/ActivityItem/index.spec.tsx +103 -0
- package/src/components/Activity/ActivityItem/index.tsx +90 -0
- package/src/components/Avatars/Avatar.tsx +56 -0
- package/src/components/Avatars/BaseAvatar/index.tsx +126 -0
- package/src/components/Avatars/BaseAvatar/utils.ts +73 -0
- package/src/components/Avatars/CompanyAvatar/__snapshots__/index.spec.tsx.snap +25 -0
- package/src/components/Avatars/CompanyAvatar/index.spec.tsx +11 -0
- package/src/components/Avatars/CompanyAvatar/index.tsx +36 -0
- package/src/components/Avatars/DateAvatar/__snapshots__/index.spec.tsx.snap +18 -0
- package/src/components/Avatars/DateAvatar/index.spec.tsx +12 -0
- package/src/components/Avatars/DateAvatar/index.tsx +22 -0
- package/src/components/Avatars/EmojiAvatar/__snapshots__/index.spec.tsx.snap +37 -0
- package/src/components/Avatars/EmojiAvatar/index.spec.tsx +15 -0
- package/src/components/Avatars/EmojiAvatar/index.tsx +37 -0
- package/src/components/Avatars/FileAvatar/__snapshots__/index.spec.tsx.snap +261 -0
- package/src/components/Avatars/FileAvatar/index.spec.tsx +43 -0
- package/src/components/Avatars/FileAvatar/index.tsx +117 -0
- package/src/components/Avatars/FileAvatar/utils.ts +103 -0
- package/src/components/Avatars/IconAvatar/__snapshots__/index.spec.tsx.snap +256 -0
- package/src/components/Avatars/IconAvatar/index.spec.tsx +16 -0
- package/src/components/Avatars/IconAvatar/index.tsx +31 -0
- package/src/components/Avatars/ModuleAvatar/index.tsx +106 -0
- package/src/components/Avatars/ModuleAvatar/modules.ts +64 -0
- package/src/components/Avatars/PersonAvatar/__snapshots__/index.spec.tsx.snap +25 -0
- package/src/components/Avatars/PersonAvatar/index.spec.tsx +13 -0
- package/src/components/Avatars/PersonAvatar/index.tsx +38 -0
- package/src/components/Avatars/TeamAvatar/__snapshots__/index.spec.tsx.snap +25 -0
- package/src/components/Avatars/TeamAvatar/index.spec.tsx +11 -0
- package/src/components/Avatars/TeamAvatar/index.tsx +36 -0
- package/src/components/Avatars/exports.ts +9 -0
- package/src/components/Avatars/types.ts +15 -0
- package/src/components/Badge/index.tsx +47 -0
- package/src/components/Button/__snapshots__/index.spec.tsx.snap +517 -0
- package/src/components/Button/index.spec.tsx +124 -0
- package/src/components/Button/index.tsx +233 -0
- package/src/components/Counter/__snapshots__/index.spec.tsx.snap +113 -0
- package/src/components/Counter/index.spec.tsx +53 -0
- package/src/components/Counter/index.tsx +59 -0
- package/src/components/ExampleComponent.tsx +22 -0
- package/src/components/Icon/README.md +63 -0
- package/src/components/Icon/__tests__/Icon.spec.tsx +35 -0
- package/src/components/Icon/index.tsx +85 -0
- package/src/components/Navigation/PageHeader/__snapshots__/index.spec.tsx.snap +242 -0
- package/src/components/Navigation/PageHeader/index.spec.tsx +198 -0
- package/src/components/Navigation/PageHeader/index.tsx +53 -0
- package/src/components/OneChip/__snapshots__/index.spec.tsx.snap +366 -0
- package/src/components/OneChip/index.spec.tsx +69 -0
- package/src/components/OneChip/index.tsx +89 -0
- package/src/components/OnePreset/__snapshots__/index.spec.tsx.snap +149 -0
- package/src/components/OnePreset/index.spec.tsx +46 -0
- package/src/components/OnePreset/index.tsx +36 -0
- package/src/components/Tags/AlertTab/__snapshots__/index.spec.tsx.snap +292 -0
- package/src/components/Tags/AlertTab/index.spec.tsx +18 -0
- package/src/components/Tags/AlertTab/index.tsx +61 -0
- package/src/components/Tags/BaseTag/index.tsx +64 -0
- package/src/components/Tags/DotTag/__snapshots__/index.spec.tsx.snap +1081 -0
- package/src/components/Tags/DotTag/index.spec.tsx +14 -0
- package/src/components/Tags/DotTag/index.tsx +54 -0
- package/src/components/Tags/RawTag/__snapshots__/index.spec.tsx.snap +213 -0
- package/src/components/Tags/RawTag/index.spec.tsx +19 -0
- package/src/components/Tags/RawTag/index.tsx +41 -0
- package/src/components/Tags/Tag.tsx +32 -0
- package/src/components/Tags/exports.ts +3 -0
- package/src/components/__tests__/ExampleComponent.spec.tsx +16 -0
- package/src/components/experimental/Lists/DataList/ItemContainer.tsx +74 -0
- package/src/components/experimental/Lists/DataList/actions/CopyAction.tsx +72 -0
- package/src/components/experimental/Lists/DataList/actions/GenericAction.tsx +37 -0
- package/src/components/experimental/Lists/DataList/index.tsx +186 -0
- package/src/components/experimental/Lists/DetailsItem/__snapshots__/index.spec.tsx.snap +759 -0
- package/src/components/experimental/Lists/DetailsItem/index.spec.tsx +81 -0
- package/src/components/experimental/Lists/DetailsItem/index.tsx +68 -0
- package/src/components/experimental/Lists/DetailsItemsList/__snapshots__/index.spec.tsx.snap +671 -0
- package/src/components/experimental/Lists/DetailsItemsList/index.spec.tsx +73 -0
- package/src/components/experimental/Lists/DetailsItemsList/index.tsx +52 -0
- package/src/icons/app/AcademicCap.tsx +31 -0
- package/src/icons/app/Add.tsx +21 -0
- package/src/icons/app/Ai.tsx +24 -0
- package/src/icons/app/Alert.tsx +16 -0
- package/src/icons/app/AlertCircle.tsx +19 -0
- package/src/icons/app/AlertCircleLine.tsx +17 -0
- package/src/icons/app/AlignTextCenter.tsx +21 -0
- package/src/icons/app/AlignTextJustify.tsx +21 -0
- package/src/icons/app/AlignTextLeft.tsx +21 -0
- package/src/icons/app/AlignTextRight.tsx +21 -0
- package/src/icons/app/Appearance.tsx +33 -0
- package/src/icons/app/Archive.tsx +21 -0
- package/src/icons/app/ArchiveOpen.tsx +21 -0
- package/src/icons/app/ArrowCycle.tsx +27 -0
- package/src/icons/app/ArrowDown.tsx +27 -0
- package/src/icons/app/ArrowLeft.tsx +21 -0
- package/src/icons/app/ArrowRight.tsx +21 -0
- package/src/icons/app/ArrowUp.tsx +21 -0
- package/src/icons/app/Bank.tsx +20 -0
- package/src/icons/app/BarGraph.tsx +21 -0
- package/src/icons/app/Bell.tsx +24 -0
- package/src/icons/app/Bold.tsx +23 -0
- package/src/icons/app/BookOpen.tsx +21 -0
- package/src/icons/app/Briefcase.tsx +18 -0
- package/src/icons/app/Bucket.tsx +23 -0
- package/src/icons/app/Building.tsx +25 -0
- package/src/icons/app/Bullet.tsx +19 -0
- package/src/icons/app/Calculator.tsx +17 -0
- package/src/icons/app/Calendar.tsx +21 -0
- package/src/icons/app/CalendarArrowDown.tsx +21 -0
- package/src/icons/app/CalendarArrowLeft.tsx +21 -0
- package/src/icons/app/CalendarArrowRight.tsx +21 -0
- package/src/icons/app/CameraPlus.tsx +22 -0
- package/src/icons/app/ChartLine.tsx +26 -0
- package/src/icons/app/ChartPie.tsx +25 -0
- package/src/icons/app/Check.tsx +21 -0
- package/src/icons/app/CheckCircle.tsx +21 -0
- package/src/icons/app/CheckCircleLine.tsx +22 -0
- package/src/icons/app/CheckDouble.tsx +21 -0
- package/src/icons/app/ChevronDown.tsx +21 -0
- package/src/icons/app/ChevronLeft.tsx +21 -0
- package/src/icons/app/ChevronRight.tsx +21 -0
- package/src/icons/app/ChevronUp.tsx +21 -0
- package/src/icons/app/Circle.tsx +16 -0
- package/src/icons/app/Clock.tsx +22 -0
- package/src/icons/app/Code.tsx +21 -0
- package/src/icons/app/Coffee.tsx +24 -0
- package/src/icons/app/Comment.tsx +19 -0
- package/src/icons/app/Completed.tsx +21 -0
- package/src/icons/app/CreditCard.tsx +21 -0
- package/src/icons/app/Cross.tsx +21 -0
- package/src/icons/app/CrossedCircle.tsx +21 -0
- package/src/icons/app/Crown.tsx +21 -0
- package/src/icons/app/Delete.tsx +21 -0
- package/src/icons/app/Deny.tsx +21 -0
- package/src/icons/app/Desktop.tsx +26 -0
- package/src/icons/app/DollarBill.tsx +22 -0
- package/src/icons/app/DottedCircle.tsx +16 -0
- package/src/icons/app/Download.tsx +21 -0
- package/src/icons/app/DropdownDefault.tsx +25 -0
- package/src/icons/app/DropdownOpen.tsx +25 -0
- package/src/icons/app/Ellipsis.tsx +36 -0
- package/src/icons/app/EllipsisHorizontal.tsx +18 -0
- package/src/icons/app/Envelope.tsx +21 -0
- package/src/icons/app/EnvelopeOpen.tsx +23 -0
- package/src/icons/app/Exit.tsx +21 -0
- package/src/icons/app/ExternalLink.tsx +21 -0
- package/src/icons/app/EyeInvisible.tsx +26 -0
- package/src/icons/app/EyeVisible.tsx +21 -0
- package/src/icons/app/FaceNegative.tsx +21 -0
- package/src/icons/app/FaceNeutral.tsx +21 -0
- package/src/icons/app/FacePositive.tsx +21 -0
- package/src/icons/app/FaceSuperNegative.tsx +21 -0
- package/src/icons/app/FaceSuperPositive.tsx +21 -0
- package/src/icons/app/Feed.tsx +21 -0
- package/src/icons/app/File.tsx +21 -0
- package/src/icons/app/FileFilled.tsx +21 -0
- package/src/icons/app/Filter.tsx +19 -0
- package/src/icons/app/Flag.tsx +21 -0
- package/src/icons/app/Folder.tsx +19 -0
- package/src/icons/app/Folders.tsx +24 -0
- package/src/icons/app/Globe.tsx +26 -0
- package/src/icons/app/Graph.tsx +26 -0
- package/src/icons/app/Handshake.tsx +29 -0
- package/src/icons/app/Heading1.tsx +21 -0
- package/src/icons/app/Heading2.tsx +21 -0
- package/src/icons/app/Heading3.tsx +21 -0
- package/src/icons/app/Heart.tsx +21 -0
- package/src/icons/app/HoldHeart.tsx +21 -0
- package/src/icons/app/Home.tsx +20 -0
- package/src/icons/app/Hub.tsx +51 -0
- package/src/icons/app/Image.tsx +21 -0
- package/src/icons/app/InProgressTask.tsx +17 -0
- package/src/icons/app/Inbox.tsx +26 -0
- package/src/icons/app/Info.tsx +21 -0
- package/src/icons/app/InfoCircle.tsx +21 -0
- package/src/icons/app/InfoCircleLine.tsx +28 -0
- package/src/icons/app/Italic.tsx +21 -0
- package/src/icons/app/Kanban.tsx +21 -0
- package/src/icons/app/Laptop.tsx +20 -0
- package/src/icons/app/LayersFront.tsx +26 -0
- package/src/icons/app/Lightbulb.tsx +26 -0
- package/src/icons/app/Link.tsx +25 -0
- package/src/icons/app/LinkRemove.tsx +20 -0
- package/src/icons/app/List.tsx +25 -0
- package/src/icons/app/LockLocked.tsx +21 -0
- package/src/icons/app/LockUnlocked.tsx +21 -0
- package/src/icons/app/LogoAvatar.tsx +23 -0
- package/src/icons/app/LogoEruditai.tsx +19 -0
- package/src/icons/app/LogoTravelperk.tsx +27 -0
- package/src/icons/app/Masonry.tsx +19 -0
- package/src/icons/app/Maximize.tsx +21 -0
- package/src/icons/app/Megaphone.tsx +21 -0
- package/src/icons/app/Menu.tsx +21 -0
- package/src/icons/app/MessageFrown.tsx +25 -0
- package/src/icons/app/MessageHeart.tsx +25 -0
- package/src/icons/app/Messages.tsx +21 -0
- package/src/icons/app/Microphone.tsx +26 -0
- package/src/icons/app/MicrophoneNegative.tsx +26 -0
- package/src/icons/app/Minimize.tsx +21 -0
- package/src/icons/app/Minus.tsx +21 -0
- package/src/icons/app/Mobile.tsx +21 -0
- package/src/icons/app/Money.tsx +26 -0
- package/src/icons/app/MoneyBag.tsx +24 -0
- package/src/icons/app/MoveDown.tsx +44 -0
- package/src/icons/app/MoveTop.tsx +34 -0
- package/src/icons/app/MoveUp.tsx +42 -0
- package/src/icons/app/Office.tsx +31 -0
- package/src/icons/app/OlList.tsx +21 -0
- package/src/icons/app/PalmTree.tsx +20 -0
- package/src/icons/app/Paperclip.tsx +20 -0
- package/src/icons/app/PartiallyCompleted.tsx +21 -0
- package/src/icons/app/PauseCircle.tsx +21 -0
- package/src/icons/app/Pencil.tsx +21 -0
- package/src/icons/app/People.tsx +27 -0
- package/src/icons/app/Person.tsx +22 -0
- package/src/icons/app/Phone.tsx +20 -0
- package/src/icons/app/Pin.tsx +22 -0
- package/src/icons/app/PixBrazil.tsx +19 -0
- package/src/icons/app/Placeholder.tsx +21 -0
- package/src/icons/app/Plane.tsx +21 -0
- package/src/icons/app/Plus.tsx +21 -0
- package/src/icons/app/Present.tsx +31 -0
- package/src/icons/app/Printer.tsx +26 -0
- package/src/icons/app/Proyector.tsx +22 -0
- package/src/icons/app/Question.tsx +22 -0
- package/src/icons/app/Quote.tsx +21 -0
- package/src/icons/app/Reaction.tsx +32 -0
- package/src/icons/app/Receipt.tsx +20 -0
- package/src/icons/app/Record.tsx +17 -0
- package/src/icons/app/RemoveFavorite.tsx +21 -0
- package/src/icons/app/Replace.tsx +21 -0
- package/src/icons/app/Reset.tsx +27 -0
- package/src/icons/app/Rocket.tsx +26 -0
- package/src/icons/app/Salad.tsx +21 -0
- package/src/icons/app/Save.tsx +27 -0
- package/src/icons/app/Schedule.tsx +32 -0
- package/src/icons/app/Search.tsx +17 -0
- package/src/icons/app/SearchPerson.tsx +24 -0
- package/src/icons/app/Settings.tsx +20 -0
- package/src/icons/app/Share.tsx +27 -0
- package/src/icons/app/Sliders.tsx +22 -0
- package/src/icons/app/SolidPause.tsx +19 -0
- package/src/icons/app/SolidPlay.tsx +19 -0
- package/src/icons/app/SolidStop.tsx +19 -0
- package/src/icons/app/Sort.tsx +21 -0
- package/src/icons/app/Sparkles.tsx +25 -0
- package/src/icons/app/Spinner.tsx +20 -0
- package/src/icons/app/Split.tsx +21 -0
- package/src/icons/app/Star.tsx +21 -0
- package/src/icons/app/StarFilled.tsx +19 -0
- package/src/icons/app/Strikethrough.tsx +21 -0
- package/src/icons/app/Suitcase.tsx +22 -0
- package/src/icons/app/Table.tsx +21 -0
- package/src/icons/app/Target.tsx +31 -0
- package/src/icons/app/TextSize.tsx +21 -0
- package/src/icons/app/Timer.tsx +27 -0
- package/src/icons/app/Underline.tsx +26 -0
- package/src/icons/app/Upload.tsx +21 -0
- package/src/icons/app/Video.tsx +23 -0
- package/src/icons/app/VideoRecorder.tsx +31 -0
- package/src/icons/app/VideoRecorderNegative.tsx +22 -0
- package/src/icons/app/Wallet.tsx +26 -0
- package/src/icons/app/Warning.tsx +21 -0
- package/src/icons/app/WhatsappChat.tsx +23 -0
- package/src/icons/app/Windows.tsx +21 -0
- package/src/icons/app/index.ts +186 -0
- package/src/icons/index.ts +5 -0
- package/src/icons/modules/Benefits.tsx +25 -0
- package/src/icons/modules/Calendar.tsx +21 -0
- package/src/icons/modules/Cards.tsx +25 -0
- package/src/icons/modules/ClockIn.tsx +21 -0
- package/src/icons/modules/Discover.tsx +25 -0
- package/src/icons/modules/Documents.tsx +19 -0
- package/src/icons/modules/Engagement.tsx +21 -0
- package/src/icons/modules/Finance.tsx +21 -0
- package/src/icons/modules/Goals.tsx +19 -0
- package/src/icons/modules/Home.tsx +19 -0
- package/src/icons/modules/Hub.tsx +20 -0
- package/src/icons/modules/Inbox.tsx +19 -0
- package/src/icons/modules/Kudos.tsx +19 -0
- package/src/icons/modules/MyDocuments.tsx +21 -0
- package/src/icons/modules/Organization.tsx +19 -0
- package/src/icons/modules/Overviews.tsx +23 -0
- package/src/icons/modules/Payroll.tsx +25 -0
- package/src/icons/modules/Performance.tsx +19 -0
- package/src/icons/modules/Profile.tsx +19 -0
- package/src/icons/modules/Projects.tsx +21 -0
- package/src/icons/modules/Recruitment.tsx +21 -0
- package/src/icons/modules/Reports.tsx +21 -0
- package/src/icons/modules/Sales.tsx +27 -0
- package/src/icons/modules/Settings.tsx +21 -0
- package/src/icons/modules/Shifts.tsx +27 -0
- package/src/icons/modules/Social.tsx +21 -0
- package/src/icons/modules/Software.tsx +19 -0
- package/src/icons/modules/Spaces.tsx +21 -0
- package/src/icons/modules/Spending.tsx +21 -0
- package/src/icons/modules/Tasks.tsx +21 -0
- package/src/icons/modules/TimeOff.tsx +21 -0
- package/src/icons/modules/TimeTracking.tsx +25 -0
- package/src/icons/modules/Trainings.tsx +19 -0
- package/src/icons/modules/Treasury.tsx +19 -0
- package/src/icons/modules/Workflows.tsx +19 -0
- package/src/icons/modules/index.ts +35 -0
- package/src/icons/types.ts +9 -0
- package/src/index.ts +18 -0
- package/src/lib/date.ts +102 -0
- package/src/lib/emojis.tsx +47 -0
- package/src/lib/iconWithClassName.ts +17 -0
- package/src/lib/text.ts +31 -0
- package/src/lib/utils.ts +6 -0
- package/src/ui/avatar.tsx +113 -0
- package/tailwind.config.ts +19 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { render, fireEvent, screen } from "@testing-library/react-native";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Button } from "./";
|
|
4
|
+
import { IconType } from "../Icon";
|
|
5
|
+
|
|
6
|
+
// Mock the Icon component
|
|
7
|
+
jest.mock("../Icon", () => ({
|
|
8
|
+
Icon: () => null,
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
// Mock dependencies
|
|
12
|
+
const mockIcon: IconType = "check" as unknown as IconType;
|
|
13
|
+
const mockOnPress = jest.fn();
|
|
14
|
+
|
|
15
|
+
describe("Button", () => {
|
|
16
|
+
const defaultProps = {
|
|
17
|
+
label: "Test Button",
|
|
18
|
+
onPress: mockOnPress,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("Snapshot - default button", () => {
|
|
26
|
+
const { toJSON } = render(<Button {...defaultProps} />);
|
|
27
|
+
|
|
28
|
+
expect(toJSON()).toMatchSnapshot();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("Snapshot - outline variant", () => {
|
|
32
|
+
const { toJSON } = render(<Button {...defaultProps} variant="outline" />);
|
|
33
|
+
|
|
34
|
+
expect(toJSON()).toMatchSnapshot();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("Snapshot - critical variant", () => {
|
|
38
|
+
const { toJSON } = render(<Button {...defaultProps} variant="critical" />);
|
|
39
|
+
|
|
40
|
+
expect(toJSON()).toMatchSnapshot();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("Snapshot - with icon", () => {
|
|
44
|
+
const { toJSON } = render(<Button {...defaultProps} icon={mockIcon} />);
|
|
45
|
+
|
|
46
|
+
expect(toJSON()).toMatchSnapshot();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("Snapshot - with emoji", () => {
|
|
50
|
+
const { toJSON } = render(<Button {...defaultProps} emoji="👋" />);
|
|
51
|
+
|
|
52
|
+
expect(toJSON()).toMatchSnapshot();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("Snapshot - disabled state", () => {
|
|
56
|
+
const { toJSON } = render(<Button {...defaultProps} disabled />);
|
|
57
|
+
|
|
58
|
+
expect(toJSON()).toMatchSnapshot();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("Snapshot - loading state", () => {
|
|
62
|
+
const { toJSON } = render(<Button {...defaultProps} loading />);
|
|
63
|
+
|
|
64
|
+
expect(toJSON()).toMatchSnapshot();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("Snapshot - different sizes", () => {
|
|
68
|
+
const sizes = ["sm", "md", "lg"] as const;
|
|
69
|
+
|
|
70
|
+
sizes.forEach((size) => {
|
|
71
|
+
const { toJSON } = render(<Button {...defaultProps} size={size} />);
|
|
72
|
+
expect(toJSON()).toMatchSnapshot();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("Snapshot - round button with hidden label", () => {
|
|
77
|
+
const { toJSON } = render(<Button {...defaultProps} round hideLabel />);
|
|
78
|
+
|
|
79
|
+
expect(toJSON()).toMatchSnapshot();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Regular component tests
|
|
83
|
+
it("renders correctly with required props", () => {
|
|
84
|
+
render(<Button {...defaultProps} />);
|
|
85
|
+
|
|
86
|
+
const button = screen.getByText("Test Button");
|
|
87
|
+
|
|
88
|
+
expect(button).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("handles press events", () => {
|
|
92
|
+
render(<Button {...defaultProps} />);
|
|
93
|
+
|
|
94
|
+
fireEvent.press(screen.getByRole("button"));
|
|
95
|
+
|
|
96
|
+
expect(mockOnPress).toHaveBeenCalled();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("does not call onPress when disabled", () => {
|
|
100
|
+
render(<Button {...defaultProps} disabled />);
|
|
101
|
+
|
|
102
|
+
fireEvent.press(screen.getByRole("button"));
|
|
103
|
+
|
|
104
|
+
expect(mockOnPress).not.toHaveBeenCalled();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("shows correct accessibility label when disabled", () => {
|
|
108
|
+
render(<Button {...defaultProps} disabled />);
|
|
109
|
+
|
|
110
|
+
const button = screen.getByRole("button");
|
|
111
|
+
|
|
112
|
+
expect(button.props.accessibilityLabel).toBe("Test Button, disabled");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("shows correct accessibility label when loading", () => {
|
|
116
|
+
render(<Button {...defaultProps} loading />);
|
|
117
|
+
|
|
118
|
+
const button = screen.getByRole("button");
|
|
119
|
+
|
|
120
|
+
expect(button.props.accessibilityLabel).toBe(
|
|
121
|
+
"Test Button, disabled, loading",
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "cva";
|
|
2
|
+
import React, { forwardRef, useState } from "react";
|
|
3
|
+
import { Pressable, Text, View } from "react-native";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
import { Icon, type IconType } from "../Icon";
|
|
6
|
+
|
|
7
|
+
export const variants = [
|
|
8
|
+
"default",
|
|
9
|
+
"outline",
|
|
10
|
+
"critical",
|
|
11
|
+
"neutral",
|
|
12
|
+
"ghost",
|
|
13
|
+
"promote",
|
|
14
|
+
] as const;
|
|
15
|
+
export type ButtonVariant = (typeof variants)[number];
|
|
16
|
+
|
|
17
|
+
export const sizes = ["sm", "md", "lg"] as const;
|
|
18
|
+
export type ButtonSize = (typeof sizes)[number];
|
|
19
|
+
|
|
20
|
+
const buttonVariants = cva({
|
|
21
|
+
base: "flex-row items-center justify-center rounded border-none grow-0",
|
|
22
|
+
variants: {
|
|
23
|
+
variant: {
|
|
24
|
+
default: "bg-f1-background-accent-bold",
|
|
25
|
+
outline: "bg-f1-background-inverse-secondary border border-f1-border",
|
|
26
|
+
neutral: "bg-f1-background-secondary",
|
|
27
|
+
critical: "bg-f1-background-secondary border border-f1-border",
|
|
28
|
+
ghost: "bg-transparent",
|
|
29
|
+
promote: "bg-f1-background-promote border border-f1-border-promote",
|
|
30
|
+
},
|
|
31
|
+
size: {
|
|
32
|
+
sm: "h-6 rounded-sm",
|
|
33
|
+
md: "h-8 rounded",
|
|
34
|
+
lg: "h-10 rounded-md",
|
|
35
|
+
},
|
|
36
|
+
disabled: {
|
|
37
|
+
true: "opacity-50",
|
|
38
|
+
false: "",
|
|
39
|
+
},
|
|
40
|
+
round: {
|
|
41
|
+
true: "aspect-square p-0",
|
|
42
|
+
false: "gap-1 px-2 sm:px-3 lg:px-4",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
defaultVariants: {
|
|
46
|
+
variant: "default",
|
|
47
|
+
size: "md",
|
|
48
|
+
disabled: false,
|
|
49
|
+
round: false,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const pressedVariants = cva({
|
|
54
|
+
base: "",
|
|
55
|
+
variants: {
|
|
56
|
+
variant: {
|
|
57
|
+
default: "bg-f1-background-accent-bold-hover",
|
|
58
|
+
outline: "bg-f1-background-tertiary border-opacity-70",
|
|
59
|
+
neutral: "bg-f1-background-secondary-hover",
|
|
60
|
+
critical: "bg-f1-background-critical-bold border-transparent",
|
|
61
|
+
ghost: "bg-f1-background-secondary-hover",
|
|
62
|
+
promote: "bg-f1-background-promote-hover",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
defaultVariants: {
|
|
66
|
+
variant: "default",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const getIconColor = (variant: ButtonVariant, isPressed: boolean) => {
|
|
71
|
+
switch (variant) {
|
|
72
|
+
case "default":
|
|
73
|
+
return "text-f1-icon-inverse";
|
|
74
|
+
case "critical":
|
|
75
|
+
return isPressed ? "text-f1-icon-inverse" : "text-f1-icon-critical-bold";
|
|
76
|
+
default:
|
|
77
|
+
return "text-f1-icon";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const getIconOnlyColor = (variant: ButtonVariant, isPressed: boolean) => {
|
|
82
|
+
switch (variant) {
|
|
83
|
+
case "critical":
|
|
84
|
+
return isPressed ? "text-f1-icon-inverse" : "text-f1-icon-critical-bold";
|
|
85
|
+
case "default":
|
|
86
|
+
return "text-f1-icon-inverse";
|
|
87
|
+
case "outline":
|
|
88
|
+
case "neutral":
|
|
89
|
+
case "ghost":
|
|
90
|
+
case "promote":
|
|
91
|
+
default:
|
|
92
|
+
return "text-f1-icon-bold";
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const getTextColorClass = (variant: ButtonVariant, isPressed: boolean) => {
|
|
97
|
+
if (isPressed && variant === "critical") {
|
|
98
|
+
return "text-f1-foreground-inverse";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
switch (variant) {
|
|
102
|
+
case "default":
|
|
103
|
+
return "text-f1-foreground-inverse";
|
|
104
|
+
case "critical":
|
|
105
|
+
return "text-f1-foreground-critical";
|
|
106
|
+
default:
|
|
107
|
+
return "text-f1-foreground";
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export interface ButtonProps extends VariantProps<typeof buttonVariants> {
|
|
112
|
+
label: string;
|
|
113
|
+
onPress?: () => void | Promise<unknown>;
|
|
114
|
+
disabled?: boolean;
|
|
115
|
+
loading?: boolean;
|
|
116
|
+
icon?: IconType;
|
|
117
|
+
emoji?: string;
|
|
118
|
+
hideLabel?: boolean;
|
|
119
|
+
className?: string;
|
|
120
|
+
accessibilityHint?: string;
|
|
121
|
+
showBadge?: boolean;
|
|
122
|
+
fullWidth?: boolean;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const Button = forwardRef<View, ButtonProps>(function Button(
|
|
126
|
+
{
|
|
127
|
+
label,
|
|
128
|
+
onPress,
|
|
129
|
+
disabled = false,
|
|
130
|
+
loading = false,
|
|
131
|
+
icon,
|
|
132
|
+
emoji,
|
|
133
|
+
hideLabel = false,
|
|
134
|
+
variant = "default",
|
|
135
|
+
size = "md",
|
|
136
|
+
round = false,
|
|
137
|
+
className,
|
|
138
|
+
accessibilityHint,
|
|
139
|
+
showBadge = false,
|
|
140
|
+
fullWidth = false,
|
|
141
|
+
},
|
|
142
|
+
ref,
|
|
143
|
+
) {
|
|
144
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
145
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
146
|
+
|
|
147
|
+
const handlePress = async () => {
|
|
148
|
+
if (!onPress || disabled || loading || isLoading) return;
|
|
149
|
+
|
|
150
|
+
const result = onPress();
|
|
151
|
+
|
|
152
|
+
if (result instanceof Promise) {
|
|
153
|
+
setIsLoading(true);
|
|
154
|
+
try {
|
|
155
|
+
await result;
|
|
156
|
+
} finally {
|
|
157
|
+
setIsLoading(false);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const isDisabled = disabled || loading || isLoading;
|
|
163
|
+
const accessibilityLabel = `${label}${isDisabled ? ", disabled" : ""}${loading || isLoading ? ", loading" : ""}`;
|
|
164
|
+
const shouldShowPressed = isPressed && !isDisabled;
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<View className={`flex ${fullWidth ? "flex-1" : "item-start"}`}>
|
|
168
|
+
<Pressable
|
|
169
|
+
ref={ref}
|
|
170
|
+
disabled={isDisabled}
|
|
171
|
+
onPressIn={() => setIsPressed(true)}
|
|
172
|
+
onPressOut={() => setIsPressed(false)}
|
|
173
|
+
onPress={handlePress}
|
|
174
|
+
className={cn(
|
|
175
|
+
buttonVariants({
|
|
176
|
+
variant,
|
|
177
|
+
size,
|
|
178
|
+
disabled: isDisabled,
|
|
179
|
+
round: hideLabel && round,
|
|
180
|
+
}),
|
|
181
|
+
shouldShowPressed && pressedVariants({ variant }),
|
|
182
|
+
className,
|
|
183
|
+
)}
|
|
184
|
+
accessibilityLabel={accessibilityLabel}
|
|
185
|
+
accessibilityRole="button"
|
|
186
|
+
accessibilityState={{
|
|
187
|
+
disabled: isDisabled,
|
|
188
|
+
busy: loading || isLoading,
|
|
189
|
+
}}
|
|
190
|
+
accessibilityHint={accessibilityHint}
|
|
191
|
+
>
|
|
192
|
+
{icon && (
|
|
193
|
+
<Icon
|
|
194
|
+
icon={icon}
|
|
195
|
+
size={size === "sm" ? "sm" : "md"}
|
|
196
|
+
className={cn(
|
|
197
|
+
hideLabel && round ? undefined : "-ml-0.5",
|
|
198
|
+
hideLabel && round
|
|
199
|
+
? getIconOnlyColor(variant, shouldShowPressed)
|
|
200
|
+
: getIconColor(variant, shouldShowPressed),
|
|
201
|
+
)}
|
|
202
|
+
/>
|
|
203
|
+
)}
|
|
204
|
+
{emoji && (
|
|
205
|
+
<Text
|
|
206
|
+
className={cn(
|
|
207
|
+
"text-base font-medium",
|
|
208
|
+
getTextColorClass(variant, shouldShowPressed),
|
|
209
|
+
)}
|
|
210
|
+
>
|
|
211
|
+
{emoji}
|
|
212
|
+
</Text>
|
|
213
|
+
)}
|
|
214
|
+
{!hideLabel && (
|
|
215
|
+
<Text
|
|
216
|
+
className={cn(
|
|
217
|
+
"text-base font-medium",
|
|
218
|
+
getTextColorClass(variant, shouldShowPressed),
|
|
219
|
+
)}
|
|
220
|
+
>
|
|
221
|
+
{label}
|
|
222
|
+
</Text>
|
|
223
|
+
)}
|
|
224
|
+
</Pressable>
|
|
225
|
+
{showBadge && variant === "outline" && (
|
|
226
|
+
<View
|
|
227
|
+
accessibilityLabel="Notification Badge"
|
|
228
|
+
className="absolute right-1.5 top-1.5 h-1.5 w-1.5 rounded-full bg-f1-icon-accent"
|
|
229
|
+
/>
|
|
230
|
+
)}
|
|
231
|
+
</View>
|
|
232
|
+
);
|
|
233
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Counter Snapshot 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
className="flex items-start"
|
|
6
|
+
>
|
|
7
|
+
<View
|
|
8
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-5 h-5 bg-f1-background-secondary border border-f1-border"
|
|
9
|
+
>
|
|
10
|
+
<Text
|
|
11
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap text-f1-foreground"
|
|
12
|
+
>
|
|
13
|
+
42
|
|
14
|
+
</Text>
|
|
15
|
+
</View>
|
|
16
|
+
</View>
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
exports[`Counter Snapshot vairan bold types 1`] = `
|
|
20
|
+
<View
|
|
21
|
+
className="flex items-start"
|
|
22
|
+
>
|
|
23
|
+
<View
|
|
24
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-5 h-5 bg-f1-background-accent-bold"
|
|
25
|
+
>
|
|
26
|
+
<Text
|
|
27
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap text-f1-foreground-inverse"
|
|
28
|
+
>
|
|
29
|
+
42
|
|
30
|
+
</Text>
|
|
31
|
+
</View>
|
|
32
|
+
</View>
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
exports[`Counter Snapshot vairan defauly types 1`] = `
|
|
36
|
+
<View
|
|
37
|
+
className="flex items-start"
|
|
38
|
+
>
|
|
39
|
+
<View
|
|
40
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-5 h-5 bg-f1-background-secondary border border-f1-border"
|
|
41
|
+
>
|
|
42
|
+
<Text
|
|
43
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap text-f1-foreground"
|
|
44
|
+
>
|
|
45
|
+
42
|
|
46
|
+
</Text>
|
|
47
|
+
</View>
|
|
48
|
+
</View>
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
exports[`Counter Snapshot vairan defauly types 2`] = `
|
|
52
|
+
<View
|
|
53
|
+
className="flex items-start"
|
|
54
|
+
>
|
|
55
|
+
<View
|
|
56
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-5 h-5 bg-f1-background-secondary border border-f1-border"
|
|
57
|
+
>
|
|
58
|
+
<Text
|
|
59
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap text-f1-foreground"
|
|
60
|
+
>
|
|
61
|
+
42
|
|
62
|
+
</Text>
|
|
63
|
+
</View>
|
|
64
|
+
</View>
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
exports[`Counter Snapshot vairan md size 1`] = `
|
|
68
|
+
<View
|
|
69
|
+
className="flex items-start"
|
|
70
|
+
>
|
|
71
|
+
<View
|
|
72
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-5 h-5 bg-f1-background-secondary border border-f1-border"
|
|
73
|
+
>
|
|
74
|
+
<Text
|
|
75
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap text-f1-foreground"
|
|
76
|
+
>
|
|
77
|
+
42
|
|
78
|
+
</Text>
|
|
79
|
+
</View>
|
|
80
|
+
</View>
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
exports[`Counter Snapshot vairan selected types 1`] = `
|
|
84
|
+
<View
|
|
85
|
+
className="flex items-start"
|
|
86
|
+
>
|
|
87
|
+
<View
|
|
88
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-5 h-5 bg-f1-background-selected-bold outline-f1-border-selected"
|
|
89
|
+
>
|
|
90
|
+
<Text
|
|
91
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap text-f1-foreground-inverse"
|
|
92
|
+
>
|
|
93
|
+
42
|
|
94
|
+
</Text>
|
|
95
|
+
</View>
|
|
96
|
+
</View>
|
|
97
|
+
`;
|
|
98
|
+
|
|
99
|
+
exports[`Counter Snapshot vairan sm size 1`] = `
|
|
100
|
+
<View
|
|
101
|
+
className="flex items-start"
|
|
102
|
+
>
|
|
103
|
+
<View
|
|
104
|
+
className="flex items-center justify-center rounded-xs grow-0 px-0.5 min-w-4 h-4 bg-f1-background-secondary border border-f1-border"
|
|
105
|
+
>
|
|
106
|
+
<Text
|
|
107
|
+
className="text-center text-sm font-medium tabular-nums whitespace-nowrap leading-none py-0.5 text-f1-foreground"
|
|
108
|
+
>
|
|
109
|
+
42
|
|
110
|
+
</Text>
|
|
111
|
+
</View>
|
|
112
|
+
</View>
|
|
113
|
+
`;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react-native";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Counter } from ".";
|
|
4
|
+
|
|
5
|
+
describe("Counter", () => {
|
|
6
|
+
const defaultProps = {
|
|
7
|
+
value: 42,
|
|
8
|
+
types: "default",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
it("Snapshot", () => {
|
|
12
|
+
const { toJSON } = render(<Counter {...defaultProps} />);
|
|
13
|
+
expect(toJSON()).toMatchSnapshot();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("Snapshot vairan defauly types", () => {
|
|
17
|
+
const { toJSON } = render(<Counter {...defaultProps} />);
|
|
18
|
+
expect(toJSON()).toMatchSnapshot();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("Snapshot vairan defauly types", () => {
|
|
22
|
+
const { toJSON } = render(<Counter {...defaultProps} type="default" />);
|
|
23
|
+
expect(toJSON()).toMatchSnapshot();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("Snapshot vairan bold types", () => {
|
|
27
|
+
const { toJSON } = render(<Counter {...defaultProps} type="bold" />);
|
|
28
|
+
expect(toJSON()).toMatchSnapshot();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("Snapshot vairan selected types", () => {
|
|
32
|
+
const { toJSON } = render(<Counter {...defaultProps} type="selected" />);
|
|
33
|
+
expect(toJSON()).toMatchSnapshot();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("Snapshot vairan md size", () => {
|
|
37
|
+
const { toJSON } = render(<Counter {...defaultProps} size="md" />);
|
|
38
|
+
expect(toJSON()).toMatchSnapshot();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("Snapshot vairan sm size", () => {
|
|
42
|
+
const { toJSON } = render(<Counter {...defaultProps} size="sm" />);
|
|
43
|
+
expect(toJSON()).toMatchSnapshot();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("renders correctly with required props", () => {
|
|
47
|
+
render(<Counter {...defaultProps} />);
|
|
48
|
+
|
|
49
|
+
const number = screen.getByText("42");
|
|
50
|
+
|
|
51
|
+
expect(number).toBeDefined();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "cva";
|
|
2
|
+
import { Text, View } from "react-native";
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
|
|
5
|
+
const counterContainerVariants = cva({
|
|
6
|
+
base: "flex items-center justify-center rounded-xs grow-0 px-0.5",
|
|
7
|
+
variants: {
|
|
8
|
+
size: {
|
|
9
|
+
md: "min-w-5 h-5",
|
|
10
|
+
sm: "min-w-4 h-4",
|
|
11
|
+
},
|
|
12
|
+
type: {
|
|
13
|
+
default: "bg-f1-background-secondary border border-f1-border",
|
|
14
|
+
selected: "bg-f1-background-selected-bold outline-f1-border-selected",
|
|
15
|
+
bold: "bg-f1-background-accent-bold",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
size: "md",
|
|
20
|
+
type: "default",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const counterTextVariants = cva({
|
|
25
|
+
base: "text-center text-sm font-medium tabular-nums whitespace-nowrap",
|
|
26
|
+
variants: {
|
|
27
|
+
size: {
|
|
28
|
+
md: "",
|
|
29
|
+
sm: "leading-none py-0.5",
|
|
30
|
+
},
|
|
31
|
+
type: {
|
|
32
|
+
default: "text-f1-foreground",
|
|
33
|
+
selected: "text-f1-foreground-inverse",
|
|
34
|
+
bold: "text-f1-foreground-inverse",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
type: "default",
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
type CounterProps = {
|
|
43
|
+
value: number;
|
|
44
|
+
maxValue?: number;
|
|
45
|
+
} & VariantProps<typeof counterContainerVariants>;
|
|
46
|
+
|
|
47
|
+
export function Counter({ size, type, value, maxValue }: CounterProps) {
|
|
48
|
+
const displayValue = maxValue && value > maxValue ? `+${maxValue}` : value;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View className="flex items-start">
|
|
52
|
+
<View className={cn(counterContainerVariants({ size, type }))}>
|
|
53
|
+
<Text className={cn(counterTextVariants({ type, size }))}>
|
|
54
|
+
{displayValue}
|
|
55
|
+
</Text>
|
|
56
|
+
</View>
|
|
57
|
+
</View>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text, View } from "react-native";
|
|
3
|
+
|
|
4
|
+
export interface ExampleComponentProps {
|
|
5
|
+
/**
|
|
6
|
+
* Optional custom text to display
|
|
7
|
+
*/
|
|
8
|
+
text?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* An example component that demonstrates system-based dark/light mode functionality
|
|
13
|
+
*/
|
|
14
|
+
export const ExampleComponent: React.FC<ExampleComponentProps> = ({
|
|
15
|
+
text = "Hello World",
|
|
16
|
+
}) => {
|
|
17
|
+
return (
|
|
18
|
+
<View className="rounded-lg bg-f1-background p-4">
|
|
19
|
+
<Text className="text-base font-medium text-f1-foreground">{text}</Text>
|
|
20
|
+
</View>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Icon Component
|
|
2
|
+
|
|
3
|
+
The Icon component is used to render SVG icons from the Factorial One Design System in React Native applications.
|
|
4
|
+
|
|
5
|
+
## Import Pattern
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
// Import the Icon component
|
|
9
|
+
import { Icon } from "@factorialco/f0-react-native";
|
|
10
|
+
|
|
11
|
+
// Import specific icons from app or modules directories
|
|
12
|
+
import { AppIcons, ModuleIcons } from "@factorialco/f0-react-native";
|
|
13
|
+
|
|
14
|
+
// Use the Icon component with the icon as a prop
|
|
15
|
+
<Icon icon={AppIcons.Archive} size="md" />
|
|
16
|
+
<Icon icon={ModuleIcons.Home} size="lg" />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
| Prop | Type | Default | Description |
|
|
22
|
+
| --------- | ---------------------------- | ------- | --------------------------------------- |
|
|
23
|
+
| icon | IconType | | The icon component to render |
|
|
24
|
+
| size | "xs" \| "sm" \| "md" \| "lg" | "md" | The size of the icon |
|
|
25
|
+
| className | string | | Additional classes for styling the icon |
|
|
26
|
+
| testID | string | | Test ID for testing |
|
|
27
|
+
| ...props | SvgProps | | Additional props for the SVG component |
|
|
28
|
+
|
|
29
|
+
## Styling with NativeWind
|
|
30
|
+
|
|
31
|
+
The Icon component is designed to work with NativeWind, allowing you to style icons using Tailwind CSS classes:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
// Style using Tailwind CSS classes
|
|
35
|
+
<Icon icon={AppIcons.Archive} className="text-f1-icon-secondary" />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Available Icons
|
|
39
|
+
|
|
40
|
+
The library includes two sets of icons:
|
|
41
|
+
|
|
42
|
+
1. **App Icons** - General purpose icons used throughout the application
|
|
43
|
+
2. **Module Icons** - Icons representing specific modules in the Factorial application
|
|
44
|
+
|
|
45
|
+
## Examples
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { Icon } from "@factorialco/f0-react-native";
|
|
49
|
+
import { AppIcons, ModuleIcons } from "@factorialco/f0-react-native";
|
|
50
|
+
|
|
51
|
+
// Basic usage
|
|
52
|
+
<Icon icon={AppIcons.Calendar} />
|
|
53
|
+
|
|
54
|
+
// With size variant
|
|
55
|
+
<Icon icon={AppIcons.ChevronDown} size="xs" />
|
|
56
|
+
<Icon icon={AppIcons.Check} size="sm" />
|
|
57
|
+
<Icon icon={ModuleIcons.Home} size="md" />
|
|
58
|
+
<Icon icon={ModuleIcons.Settings} size="lg" />
|
|
59
|
+
|
|
60
|
+
// With color styling
|
|
61
|
+
<Icon icon={AppIcons.Heart} className="text-red-500" />
|
|
62
|
+
<Icon icon={AppIcons.InfoCircle} className="text-blue-500" />
|
|
63
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { render } from "@testing-library/react-native";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Icon } from "../index";
|
|
4
|
+
import { Archive } from "../../../icons/app";
|
|
5
|
+
import { Home } from "../../../icons/modules";
|
|
6
|
+
|
|
7
|
+
describe("Icon", () => {
|
|
8
|
+
it("renders correctly with an app icon", () => {
|
|
9
|
+
const { getByTestId } = render(<Icon icon={Archive} testID="icon" />);
|
|
10
|
+
expect(getByTestId("icon")).toBeTruthy();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("renders correctly with a module icon", () => {
|
|
14
|
+
const { getByTestId } = render(<Icon icon={Home} testID="icon" />);
|
|
15
|
+
expect(getByTestId("icon")).toBeTruthy();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("applies the correct size class", () => {
|
|
19
|
+
const { getByTestId } = render(
|
|
20
|
+
<Icon icon={Archive} size="lg" testID="icon" />,
|
|
21
|
+
);
|
|
22
|
+
// In a real test environment, we could check the actual style props applied
|
|
23
|
+
// but for now we just ensure it renders
|
|
24
|
+
expect(getByTestId("icon")).toBeTruthy();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("applies custom className correctly", () => {
|
|
28
|
+
const { getByTestId } = render(
|
|
29
|
+
<Icon icon={Archive} className="text-red-500" testID="icon" />,
|
|
30
|
+
);
|
|
31
|
+
// In a real test environment, we could check the actual style props applied
|
|
32
|
+
// but for now we just ensure it renders
|
|
33
|
+
expect(getByTestId("icon")).toBeTruthy();
|
|
34
|
+
});
|
|
35
|
+
});
|