ionbase-ui 0.16.0 → 0.18.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 +71 -7
- package/dist/meta/Alert.json +269 -0
- package/dist/meta/Avatar.json +97 -0
- package/dist/meta/AvatarGroup.json +82 -0
- package/dist/meta/Badge.json +83 -0
- package/dist/meta/Button.json +556 -0
- package/dist/meta/Checkbox.json +113 -0
- package/dist/meta/Divider.json +30 -0
- package/dist/meta/FullCard.json +97 -0
- package/dist/meta/Header.json +91 -0
- package/dist/meta/Icon.json +35 -0
- package/dist/meta/Input.json +558 -0
- package/dist/meta/Link.json +239 -0
- package/dist/meta/Logo.json +46 -0
- package/dist/meta/LogoMark.json +41 -0
- package/dist/meta/Menu.json +50 -0
- package/dist/meta/MenuItem.json +75 -0
- package/dist/meta/Modal.json +241 -0
- package/dist/meta/NavItem.json +76 -0
- package/dist/meta/PhoneInput.json +472 -0
- package/dist/meta/Popover.json +124 -0
- package/dist/meta/Radio.json +104 -0
- package/dist/meta/RadioGroup.json +126 -0
- package/dist/meta/ScrollProgress.json +63 -0
- package/dist/meta/Select.json +195 -0
- package/dist/meta/TabItem.json +15 -0
- package/dist/meta/Table.json +135 -0
- package/dist/meta/TableBody.json +43 -0
- package/dist/meta/TableCell.json +105 -0
- package/dist/meta/TableHead.json +43 -0
- package/dist/meta/TableRow.json +56 -0
- package/dist/meta/Tabs.json +186 -0
- package/dist/meta/Toast.json +105 -0
- package/dist/meta/ToastProvider.json +75 -0
- package/dist/meta/Toggle.json +102 -0
- package/dist/meta/Tooltip.json +78 -0
- package/dist/meta/components.json +4816 -0
- package/dist/meta/contrast.json +3608 -0
- package/dist/meta/index.json +479 -0
- package/dist/styles/alert.css +10 -5
- package/dist/styles/tokens/base.css +25 -25
- package/dist/styles/tokens/theme-dark.css +11 -11
- package/dist/tokens/index.d.ts +8 -8
- package/dist/tokens/index.js +8 -8
- package/eslint-plugin/index.js +64 -0
- package/eslint-plugin/meta-data.js +66 -0
- package/eslint-plugin/rules/needs-accessible-name.js +88 -0
- package/eslint-plugin/rules/no-deprecated-props.js +74 -0
- package/eslint-plugin/rules/no-known-contrast-failure.js +75 -0
- package/eslint-plugin/rules/no-raw-style-values.js +107 -0
- package/eslint-plugin/rules/one-primary-action.js +128 -0
- package/package.json +33 -7
- package/stylelint-config.js +144 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Divider",
|
|
3
|
+
"source": "src/components/Divider.tsx",
|
|
4
|
+
"propsType": "DividerProps",
|
|
5
|
+
"description": "A single `<hr>`, matching Figma's `Border` (70:22153).\n\n`<hr>` rather than a styled `<div>`: it is a semantic thematic break, so a\nscreen reader announces it as one, and it needs no `role` to get there.\n`aria-orientation` is set for the vertical case, since a vertical rule\ninside a horizontal toolbar is the one shape a screen reader cannot infer\nfrom the element alone.",
|
|
6
|
+
"import": "import { Divider } from 'ionbase-ui';",
|
|
7
|
+
"stylesheet": "src/styles/divider.css",
|
|
8
|
+
"tokens": [
|
|
9
|
+
"--border-strong",
|
|
10
|
+
"--border-width-default"
|
|
11
|
+
],
|
|
12
|
+
"props": {
|
|
13
|
+
"orientation": {
|
|
14
|
+
"type": "DividerOrientation | undefined",
|
|
15
|
+
"required": false,
|
|
16
|
+
"origin": "own",
|
|
17
|
+
"description": "Matches Figma's `Style` variant.",
|
|
18
|
+
"values": [
|
|
19
|
+
"horizontal",
|
|
20
|
+
"vertical"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"propCounts": {
|
|
25
|
+
"own": 1,
|
|
26
|
+
"aria": 0,
|
|
27
|
+
"dom": 278,
|
|
28
|
+
"other": 0
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "FullCard",
|
|
3
|
+
"source": "src/components/FullCard.tsx",
|
|
4
|
+
"propsType": "FullCardProps",
|
|
5
|
+
"description": "Full Card — the full-bleed case study row from Figma `Full Card` (592:857).\n\nA text column beside a framed media panel, split down the middle, mirrored\nby the `Alignment` variant.\n\nThe split holds from 1080 and stacks below it, media above content in BOTH\nalignments — `Alignment` names a horizontal side and\nstops meaning anything once there is one column, so it does not get to\ndecide the vertical order too. Size is a media query, not a prop, the same\ncall Header makes about Device.\n\nWHY THE `show*` BOOLEANS ARE GONE\n\nFigma carries `Show Eyebrow`, `Show Description` and `Show Actions` beside\nthe slots they gate, because a Figma component instance always holds every\nlayer and needs a switch to hide one. React has no such constraint — an\nabsent prop is the switch. Badge made the same call with `Show Dot`, and\nkeeping both would have let `showActions` and `actions` disagree.\n\n`headline` is required, and it is the only required prop. The heading is\nwhat makes this a section rather than a decorated div, and every other part\nof the card is optional in Figma too.\n\nNo `'use client'`: nothing here is stateful or interactive. The interactive\nparts arrive through `actions`, and they carry their own boundary.",
|
|
6
|
+
"import": "import { FullCard } from 'ionbase-ui';",
|
|
7
|
+
"stylesheet": "src/styles/full-card.css",
|
|
8
|
+
"tokens": [
|
|
9
|
+
"--border-default",
|
|
10
|
+
"--border-width-default",
|
|
11
|
+
"--font-family-sans",
|
|
12
|
+
"--font-weight-regular",
|
|
13
|
+
"--font-weight-semibold",
|
|
14
|
+
"--ion-full-card-gap",
|
|
15
|
+
"--ion-full-card-media-gutter",
|
|
16
|
+
"--ion-full-card-media-min-height",
|
|
17
|
+
"--ion-full-card-media-width",
|
|
18
|
+
"--ion-full-card-padding-x",
|
|
19
|
+
"--ion-full-card-padding-y",
|
|
20
|
+
"--radius-5xl",
|
|
21
|
+
"--radius-6xl",
|
|
22
|
+
"--radius-none",
|
|
23
|
+
"--spacing-0",
|
|
24
|
+
"--spacing-24",
|
|
25
|
+
"--spacing-32",
|
|
26
|
+
"--spacing-48",
|
|
27
|
+
"--spacing-8",
|
|
28
|
+
"--surface-default",
|
|
29
|
+
"--surface-page",
|
|
30
|
+
"--surface-sunken",
|
|
31
|
+
"--text-default",
|
|
32
|
+
"--text-secondary",
|
|
33
|
+
"--type-body-sm",
|
|
34
|
+
"--type-body-sm-line-height",
|
|
35
|
+
"--type-h3",
|
|
36
|
+
"--type-h3-line-height"
|
|
37
|
+
],
|
|
38
|
+
"props": {
|
|
39
|
+
"alignment": {
|
|
40
|
+
"type": "FullCardAlignment | undefined",
|
|
41
|
+
"required": false,
|
|
42
|
+
"origin": "own",
|
|
43
|
+
"description": "Which side the media panel sits on. Matches Figma's `Alignment` variant,\nwhose `Right` / `Left` name the media, not the text.",
|
|
44
|
+
"values": [
|
|
45
|
+
"right",
|
|
46
|
+
"left"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"eyebrow": {
|
|
50
|
+
"type": "React.ReactNode",
|
|
51
|
+
"required": false,
|
|
52
|
+
"origin": "own",
|
|
53
|
+
"description": "Figma's `Eyebrow` slot — a Badge in the design, but any node works."
|
|
54
|
+
},
|
|
55
|
+
"headline": {
|
|
56
|
+
"type": "React.ReactNode",
|
|
57
|
+
"required": true,
|
|
58
|
+
"origin": "own",
|
|
59
|
+
"description": "Figma's `Headline`. Required: a card with no headline has no accessible name."
|
|
60
|
+
},
|
|
61
|
+
"description": {
|
|
62
|
+
"type": "React.ReactNode",
|
|
63
|
+
"required": false,
|
|
64
|
+
"origin": "own",
|
|
65
|
+
"description": "Figma's `Description`."
|
|
66
|
+
},
|
|
67
|
+
"actions": {
|
|
68
|
+
"type": "React.ReactNode",
|
|
69
|
+
"required": false,
|
|
70
|
+
"origin": "own",
|
|
71
|
+
"description": "Figma's `Actions` slot — a secondary Button in the design."
|
|
72
|
+
},
|
|
73
|
+
"media": {
|
|
74
|
+
"type": "React.ReactNode",
|
|
75
|
+
"required": false,
|
|
76
|
+
"origin": "own",
|
|
77
|
+
"description": "Figma's `Media` slot. Rendered inside the framed screen holder, so pass\nthe screenshot or embed itself, not the frame."
|
|
78
|
+
},
|
|
79
|
+
"headingLevel": {
|
|
80
|
+
"type": "FullCardHeadingLevel | undefined",
|
|
81
|
+
"required": false,
|
|
82
|
+
"origin": "own",
|
|
83
|
+
"description": "Heading element for the headline. Defaults to `h3`, matching the `Type/H3`\ntext style Figma applies — but the level is a document-outline decision\nonly the page knows, so it is a prop rather than a constant."
|
|
84
|
+
},
|
|
85
|
+
"children": {
|
|
86
|
+
"type": "React.ReactNode",
|
|
87
|
+
"required": false,
|
|
88
|
+
"origin": "own"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"propCounts": {
|
|
92
|
+
"own": 8,
|
|
93
|
+
"aria": 0,
|
|
94
|
+
"dom": 276,
|
|
95
|
+
"other": 0
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Header",
|
|
3
|
+
"source": "src/components/Header.tsx",
|
|
4
|
+
"propsType": "HeaderProps",
|
|
5
|
+
"description": "Header renders Figma's four Device variants — Desktop, Tablet,\nMobile-Closed, Mobile-Open — from one DOM tree.\n\nTWO AXES, AND THEY ARE NOT THE SAME KIND OF THING\n\nFigma spells Device as a single four-way variant, but it is really two: a\n*breakpoint* (Desktop / Tablet / Mobile) and a *state* (Closed / Open). They\nare modelled differently here because they are known by different people.\n\n Breakpoint is a media query. It is the one variant axis in the system the\n browser already knows the answer to — a header is Mobile because the\n viewport is narrow — and having React duplicate that judgement is how the\n two drift apart. Breakpoints match the Breakpoint collection's container\n widths: Tablet below 1216, Mobile below 896.\n\n Open/Closed is a prop, because only the caller knows. It follows the\n controlled/uncontrolled pair the rest of the system uses.\n\nONE TREE, TWO LAYOUTS\n\n`center` and `end` sit inline in the bar on Desktop and Tablet, and inside\nthe dropped Menu-Container on Mobile-Open. They are rendered once, in one\nwrapper, which is `display: contents` above the mobile breakpoint and an\nabsolutely positioned panel below it. Rendering them twice — or moving them\nwith JavaScript — would mean the same nav link exists twice in the\naccessibility tree, and would reset any state a caller put in a slot every\ntime the viewport crossed 896px.\n\nThe centre slot is no longer hidden on Tablet. Figma's Tablet variant ships\nit populated; the previous release collapsed it, which was correct for the\nprevious design and is not for this one.\n\nA `<header>` element with no explicit role: it is a landmark already when it\nis a direct child of body, which is where a page header sits.",
|
|
6
|
+
"import": "import { Header } from 'ionbase-ui';",
|
|
7
|
+
"stylesheet": "src/styles/header.css",
|
|
8
|
+
"tokens": [
|
|
9
|
+
"--border-default",
|
|
10
|
+
"--border-strong",
|
|
11
|
+
"--border-width-default",
|
|
12
|
+
"--border-width-thick",
|
|
13
|
+
"--font-family-sans",
|
|
14
|
+
"--icon-default",
|
|
15
|
+
"--icon-size-sm",
|
|
16
|
+
"--ion-header-center-gap",
|
|
17
|
+
"--ion-header-end-gap",
|
|
18
|
+
"--ion-header-height",
|
|
19
|
+
"--ion-header-padding-x",
|
|
20
|
+
"--ion-header-padding-y",
|
|
21
|
+
"--ion-shadow-raised-lifted-xs",
|
|
22
|
+
"--radius-md",
|
|
23
|
+
"--radius-sm",
|
|
24
|
+
"--ring-focus",
|
|
25
|
+
"--spacing-12",
|
|
26
|
+
"--spacing-16",
|
|
27
|
+
"--spacing-2",
|
|
28
|
+
"--spacing-24",
|
|
29
|
+
"--spacing-32",
|
|
30
|
+
"--spacing-4",
|
|
31
|
+
"--spacing-48",
|
|
32
|
+
"--spacing-64",
|
|
33
|
+
"--spacing-8",
|
|
34
|
+
"--surface-default"
|
|
35
|
+
],
|
|
36
|
+
"props": {
|
|
37
|
+
"brand": {
|
|
38
|
+
"type": "React.ReactNode",
|
|
39
|
+
"required": false,
|
|
40
|
+
"origin": "own",
|
|
41
|
+
"description": "Figma's Logo slot. Rendered at the start, never shrinks."
|
|
42
|
+
},
|
|
43
|
+
"center": {
|
|
44
|
+
"type": "React.ReactNode",
|
|
45
|
+
"required": false,
|
|
46
|
+
"origin": "own",
|
|
47
|
+
"description": "Figma's `Center Slot` — nav items. Inline on Desktop and Tablet; moves\ninto the Mobile-Open menu below the mobile breakpoint."
|
|
48
|
+
},
|
|
49
|
+
"end": {
|
|
50
|
+
"type": "React.ReactNode",
|
|
51
|
+
"required": false,
|
|
52
|
+
"origin": "own",
|
|
53
|
+
"description": "Figma's `End Slot` — buttons and actions. Same placement rules as `center`."
|
|
54
|
+
},
|
|
55
|
+
"open": {
|
|
56
|
+
"type": "boolean | undefined",
|
|
57
|
+
"required": false,
|
|
58
|
+
"origin": "own",
|
|
59
|
+
"description": "Controlled Mobile-Open state. Pair with `onOpenChange`."
|
|
60
|
+
},
|
|
61
|
+
"defaultOpen": {
|
|
62
|
+
"type": "boolean | undefined",
|
|
63
|
+
"required": false,
|
|
64
|
+
"origin": "own",
|
|
65
|
+
"description": "Initial Mobile-Open state when uncontrolled."
|
|
66
|
+
},
|
|
67
|
+
"onOpenChange": {
|
|
68
|
+
"type": "((open: boolean) => void) | undefined",
|
|
69
|
+
"required": false,
|
|
70
|
+
"origin": "own",
|
|
71
|
+
"description": "Fires whenever the menu toggle changes the state, controlled or not."
|
|
72
|
+
},
|
|
73
|
+
"menuLabel": {
|
|
74
|
+
"type": "string | undefined",
|
|
75
|
+
"required": false,
|
|
76
|
+
"origin": "own",
|
|
77
|
+
"description": "Accessible name for the mobile menu toggle."
|
|
78
|
+
},
|
|
79
|
+
"children": {
|
|
80
|
+
"type": "React.ReactNode",
|
|
81
|
+
"required": false,
|
|
82
|
+
"origin": "own"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"propCounts": {
|
|
86
|
+
"own": 8,
|
|
87
|
+
"aria": 0,
|
|
88
|
+
"dom": 276,
|
|
89
|
+
"other": 0
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Icon",
|
|
3
|
+
"source": "src/Icon.tsx",
|
|
4
|
+
"propsType": "IconProps",
|
|
5
|
+
"description": "Wrapper that applies the design system's icon sizing and accessibility\ndefaults to whatever icon component you hand it.\n\n import { Plus } from 'lucide-react';\n <Icon as={Plus} size=\"sm\" />\n <Icon as={Plus} label=\"Add item\" /> // meaningful, gets an a11y name\n\nTakes the icon as a prop rather than re-exporting a set: a barrel of a\nthousand-plus icons defeats tree-shaking in several bundlers, and pinning one\nicon library would force it on every consumer. You import the one icon you\nneed, from whichever library you use, and it is the only one bundled.",
|
|
6
|
+
"import": "import { Icon } from 'ionbase-ui';",
|
|
7
|
+
"stylesheet": "src/styles/icon.css",
|
|
8
|
+
"tokens": [],
|
|
9
|
+
"props": {
|
|
10
|
+
"as": {
|
|
11
|
+
"type": "IconComponent",
|
|
12
|
+
"required": true,
|
|
13
|
+
"origin": "own",
|
|
14
|
+
"description": "The icon component to render, e.g. `import { Plus } from 'lucide-react'`.\nAny SVG component works — the design system does not ship an icon set."
|
|
15
|
+
},
|
|
16
|
+
"size": {
|
|
17
|
+
"type": "\"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xs\" | \"xs\" | (string & {}) | undefined",
|
|
18
|
+
"required": false,
|
|
19
|
+
"origin": "own",
|
|
20
|
+
"description": "A rung on the `icon-size` ladder — `2xs` 12, `xs` 14, `sm` 16, `md` 20,\n`lg` 24, `xl` 32 — or any CSS length for a one-off. Omit to inherit the surrounding\nfont size, which is what lets an icon sit correctly inside a Button without\nthe Button having to know anything about this component."
|
|
21
|
+
},
|
|
22
|
+
"label": {
|
|
23
|
+
"type": "string | undefined",
|
|
24
|
+
"required": false,
|
|
25
|
+
"origin": "own",
|
|
26
|
+
"description": "Accessible name. Provide it when the icon carries meaning on its own — an\nicon-only button, a status marker. Omit it for decoration next to a visible\nlabel, and the icon is hidden from assistive tech instead of read out twice."
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"propCounts": {
|
|
30
|
+
"own": 3,
|
|
31
|
+
"aria": 0,
|
|
32
|
+
"dom": 487,
|
|
33
|
+
"other": 0
|
|
34
|
+
}
|
|
35
|
+
}
|