@hawiyah/react 0.0.0-stage → 0.2.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/LICENSE +73 -0
- package/NOTICE +19 -0
- package/PORTAL.md +74 -0
- package/README.md +461 -2
- package/dist/calendar.d.ts +52 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +148 -0
- package/dist/calendar.js.map +1 -0
- package/dist/content-navigation.d.ts +15 -0
- package/dist/content-navigation.d.ts.map +1 -0
- package/dist/content-navigation.js +29 -0
- package/dist/content-navigation.js.map +1 -0
- package/dist/display.d.ts +421 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +208 -0
- package/dist/display.js.map +1 -0
- package/dist/expanded-content.d.ts +217 -0
- package/dist/expanded-content.d.ts.map +1 -0
- package/dist/expanded-content.js +124 -0
- package/dist/expanded-content.js.map +1 -0
- package/dist/expanded-controls.d.ts +107 -0
- package/dist/expanded-controls.d.ts.map +1 -0
- package/dist/expanded-controls.js +142 -0
- package/dist/expanded-controls.js.map +1 -0
- package/dist/expanded-interactive.d.ts +116 -0
- package/dist/expanded-interactive.d.ts.map +1 -0
- package/dist/expanded-interactive.js +204 -0
- package/dist/expanded-interactive.js.map +1 -0
- package/dist/expanded-layout.d.ts +80 -0
- package/dist/expanded-layout.d.ts.map +1 -0
- package/dist/expanded-layout.js +26 -0
- package/dist/expanded-layout.js.map +1 -0
- package/dist/expanded-shared.d.ts +3 -0
- package/dist/expanded-shared.d.ts.map +1 -0
- package/dist/expanded-shared.js +14 -0
- package/dist/expanded-shared.js.map +1 -0
- package/dist/file-upload-list.d.ts +10 -0
- package/dist/file-upload-list.d.ts.map +1 -0
- package/dist/file-upload-list.js +7 -0
- package/dist/file-upload-list.js.map +1 -0
- package/dist/forms.d.ts +34 -0
- package/dist/forms.d.ts.map +1 -0
- package/dist/forms.js +65 -0
- package/dist/forms.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive.d.ts +60 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +321 -0
- package/dist/interactive.js.map +1 -0
- package/dist/mobile-top-bar.d.ts +14 -0
- package/dist/mobile-top-bar.d.ts.map +1 -0
- package/dist/mobile-top-bar.js +8 -0
- package/dist/mobile-top-bar.js.map +1 -0
- package/dist/navigation-drawer.d.ts +20 -0
- package/dist/navigation-drawer.d.ts.map +1 -0
- package/dist/navigation-drawer.js +37 -0
- package/dist/navigation-drawer.js.map +1 -0
- package/dist/portal.d.ts +27 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +16 -0
- package/dist/portal.js.map +1 -0
- package/dist/search-field.d.ts +15 -0
- package/dist/search-field.d.ts.map +1 -0
- package/dist/search-field.js +113 -0
- package/dist/search-field.js.map +1 -0
- package/dist/shared.d.ts +35 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +78 -0
- package/dist/shared.js.map +1 -0
- package/dist/site-verification.d.ts +10 -0
- package/dist/site-verification.d.ts.map +1 -0
- package/dist/site-verification.js +16 -0
- package/dist/site-verification.js.map +1 -0
- package/package.json +54 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
|
10
|
+
|
|
11
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
|
12
|
+
|
|
13
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
|
14
|
+
|
|
15
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
|
16
|
+
|
|
17
|
+
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
|
18
|
+
|
|
19
|
+
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
|
20
|
+
|
|
21
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
|
22
|
+
|
|
23
|
+
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
|
24
|
+
|
|
25
|
+
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
|
26
|
+
|
|
27
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
|
28
|
+
|
|
29
|
+
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
|
30
|
+
|
|
31
|
+
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
|
32
|
+
|
|
33
|
+
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
|
34
|
+
|
|
35
|
+
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
|
36
|
+
|
|
37
|
+
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
|
38
|
+
|
|
39
|
+
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
|
40
|
+
|
|
41
|
+
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
|
42
|
+
|
|
43
|
+
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
|
44
|
+
|
|
45
|
+
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
|
46
|
+
|
|
47
|
+
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
|
48
|
+
|
|
49
|
+
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
|
50
|
+
|
|
51
|
+
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
|
52
|
+
|
|
53
|
+
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
|
54
|
+
|
|
55
|
+
END OF TERMS AND CONDITIONS
|
|
56
|
+
|
|
57
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
58
|
+
|
|
59
|
+
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
|
60
|
+
|
|
61
|
+
Copyright [yyyy] [name of copyright owner]
|
|
62
|
+
|
|
63
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
64
|
+
you may not use this file except in compliance with the License.
|
|
65
|
+
You may obtain a copy of the License at
|
|
66
|
+
|
|
67
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
68
|
+
|
|
69
|
+
Unless required by applicable law or agreed to in writing, software
|
|
70
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
71
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
72
|
+
See the License for the specific language governing permissions and
|
|
73
|
+
limitations under the License.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Hawiyah — هوية
|
|
2
|
+
|
|
3
|
+
تم التطوير بواسطة فريق التطوير في قطاع المنصات الوطنية - مركز المعلومات الوطني
|
|
4
|
+
Developed by the Development Team in the National Platforms Sector — National Information Center.
|
|
5
|
+
|
|
6
|
+
Copyright 2026 Mohamed Embarak
|
|
7
|
+
|
|
8
|
+
Licensed under the Apache License, Version 2.0. See LICENSE.
|
|
9
|
+
|
|
10
|
+
This distribution includes an Umm al-Qura calendar table derived from
|
|
11
|
+
HijriDate 2.3.0, Copyright (c) 2018 Mohammed Alshehri, licensed under MIT.
|
|
12
|
+
The full notice and provenance are in packages/core/third-party in the
|
|
13
|
+
source repository and third-party in the core package.
|
|
14
|
+
|
|
15
|
+
Brand source fonts are licensed separately under the SIL Open Font License
|
|
16
|
+
1.1. The unmodified notices accompany their files in brand/third-party.
|
|
17
|
+
Font software and third-party dependencies retain their own licenses.
|
|
18
|
+
The Hawiyah name and identity do not imply endorsement by Saudi Arabia's
|
|
19
|
+
Digital Government Authority. Apache 2.0 does not grant trademark rights.
|
package/PORTAL.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Portal layout
|
|
2
|
+
|
|
3
|
+
`PortalLayout` composes `PortalHeader`, optional `SecondaryNav`, `Breadcrumb`,
|
|
4
|
+
a focusable main container and `PortalFooter`. It defaults to Arabic and RTL.
|
|
5
|
+
It is a public portal shell; keep application routing and page content in the app.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { PortalLayout } from '@hawiyah/react';
|
|
9
|
+
import '@hawiyah/styles/styles.css';
|
|
10
|
+
|
|
11
|
+
<PortalLayout brand="هوية"
|
|
12
|
+
headerProps={{ brandHref: '/', navigation: [{ label: 'الخدمات', href: '/services', current: true }] }}
|
|
13
|
+
secondaryNavigation={[{ label: 'دليل الخدمات', href: '/services', current: true }]}
|
|
14
|
+
breadcrumbs={[{ label: 'الرئيسية', href: '/' }, { label: 'الخدمات', current: true }]}
|
|
15
|
+
footerProps={{ links: [{ label: 'الخصوصية', href: '/privacy' }] }}>
|
|
16
|
+
<h1>الخدمات</h1>
|
|
17
|
+
</PortalLayout>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`headerProps` accepts the existing header API plus `menuLabel`, `navigationId`,
|
|
21
|
+
and `navigationLabel`. `actions`/`notice` remain composable React nodes. Supply
|
|
22
|
+
your actual brand SVG as `brand`; no government artwork is inferred. `footerProps`
|
|
23
|
+
accepts the existing footer's brand, description, links, linksLabel and legal.
|
|
24
|
+
`mainId` is generated with React `useId` unless supplied. `skipLabel`,
|
|
25
|
+
`breadcrumbLabel` and `secondaryLabel` override the Arabic accessible labels.
|
|
26
|
+
|
|
27
|
+
For English, set `lang="en" dir="ltr"` and translate the content and labels,
|
|
28
|
+
including `skipLabel`, `breadcrumbLabel`, `secondaryLabel`,
|
|
29
|
+
`headerProps.navigationLabel`, `headerProps.menuLabel`, `footerProps.linksLabel`.
|
|
30
|
+
Language and direction are independent props.
|
|
31
|
+
|
|
32
|
+
Standalone `PortalHeader` adds a mobile disclosure when `navigation` has items;
|
|
33
|
+
set `mainId` to render its skip link. Escape closes and focuses the toggle;
|
|
34
|
+
selection, outside press and focus leaving close it. Tab is not trapped. The
|
|
35
|
+
links stay visible at desktop widths. Multiple headers receive separate IDs.
|
|
36
|
+
`SecondaryNav` takes `items` and `label`; these are ordinary page links with
|
|
37
|
+
`aria-current`, not tabs or menus.
|
|
38
|
+
|
|
39
|
+
The 48rem disclosure breakpoint is an intentional Hawiyah policy. The layout uses
|
|
40
|
+
shared tokens in DGA, Hawiyah and custom themes, and introduces no animation.
|
|
41
|
+
Source-informed composition does not claim pixel parity or DGA certification.
|
|
42
|
+
|
|
43
|
+
## Mobile navigation bar
|
|
44
|
+
|
|
45
|
+
Use `variant="mobile"` on `SecondaryNav` (React/Vue) or `hw-secondary-nav`
|
|
46
|
+
(Angular). Items accept an optional decorative `icon` name from the bundled icon
|
|
47
|
+
stylesheet, such as `home-01`, `search-01` or `menu-01`; labels remain required.
|
|
48
|
+
Vanilla uses `data-variant="mobile"` and the same semantic HTML:
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<nav class="hw-secondary-nav" data-variant="mobile" aria-label="تنقل الجوال">
|
|
52
|
+
<ul>
|
|
53
|
+
<li><a href="/" aria-current="page"><span class="hw-icon" data-icon="home-01" aria-hidden="true"></span><span>الرئيسية</span></a></li>
|
|
54
|
+
<li><a href="/services"><span class="hw-icon" data-icon="search-01" aria-hidden="true"></span><span>الخدمات</span></a></li>
|
|
55
|
+
</ul>
|
|
56
|
+
</nav>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The bar uses equal-width items, 24 px icons, a 70 px minimum height, wrapped labels
|
|
60
|
+
and a top current-page indicator. It is in normal flow and does not cover page
|
|
61
|
+
content. Safe-area bottom padding accommodates mobile devices; the source OS
|
|
62
|
+
home indicator is not reproduced. The application owns route/current updates.
|
|
63
|
+
These are page links, not content tabs: preserve native Tab/Enter navigation.
|
|
64
|
+
|
|
65
|
+
DGA/custom color transitions use `--hw-duration-tab-bar: 300ms` and
|
|
66
|
+
`--hw-ease-tab-bar: cubic-bezier(0, 0, 0.58, 1)`. Hawiyah remains immediate by
|
|
67
|
+
default. Reduced motion removes transitions; forced colors retains the selected
|
|
68
|
+
top border and keyboard focus. Hover does not mark a route selected.
|
|
69
|
+
|
|
70
|
+
Source Mobile `8332:24202` → `8332:24242` → `8332:24282` supports color changes,
|
|
71
|
+
not a sliding indicator or tab-panel animation. Semantic colors adapt to theme;
|
|
72
|
+
icon color follows the label, since imported icon override endpoints were not
|
|
73
|
+
resolved. Arabic width differs from English in the source, so no fixed item
|
|
74
|
+
width is imposed. This is a source-informed composition, not certified parity.
|
package/README.md
CHANGED
|
@@ -1,3 +1,462 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @hawiyah/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Native React 19 components for Hawiyah — هوية, a UI library built to comply with
|
|
4
|
+
the DGA Platforms Code. React owns
|
|
5
|
+
all rendered elements. No vanilla controller is mounted into a React tree.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { useState } from 'react';
|
|
9
|
+
import '@hawiyah/styles/styles.css';
|
|
10
|
+
// Optional, only when the application wants the reset:
|
|
11
|
+
import '@hawiyah/styles/reset.css';
|
|
12
|
+
import { Button, Combobox, Dialog, TextField } from '@hawiyah/react';
|
|
13
|
+
|
|
14
|
+
function Application() {
|
|
15
|
+
const [city, setCity] = useState('');
|
|
16
|
+
return (
|
|
17
|
+
<form>
|
|
18
|
+
<TextField label="الاسم الكامل" name="name" autoComplete="name" required />
|
|
19
|
+
<Combobox
|
|
20
|
+
label="المدينة"
|
|
21
|
+
name="city"
|
|
22
|
+
options={[{ value: 'riyadh', label: 'الرياض' }]}
|
|
23
|
+
value={city}
|
|
24
|
+
onValueChange={setCity}
|
|
25
|
+
required
|
|
26
|
+
/>
|
|
27
|
+
<Button type="submit">متابعة</Button>
|
|
28
|
+
</form>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Install with `npm install @hawiyah/styles @hawiyah/react`. This is a pre-1.0
|
|
34
|
+
release, so a minor version may still change its API. React and React DOM are
|
|
35
|
+
peers; `@hawiyah/core` provides the shared, pure keyboard and combobox behavior.
|
|
36
|
+
Styles are never imported implicitly. When consuming this repository's workspace
|
|
37
|
+
instead of npm, build the packages before importing their exports. Importing and server-rendering this package require no browser globals.
|
|
38
|
+
Stable associations use React `useId`, including during hydration.
|
|
39
|
+
|
|
40
|
+
## Common conventions
|
|
41
|
+
|
|
42
|
+
Native attributes, events, `className`, ARIA attributes and React 19 `ref` props
|
|
43
|
+
are passed to the component's principal native element. `TextField`, `Textarea`,
|
|
44
|
+
`Select`, `Checkbox`, `Radio`, `Switch`, `Combobox` and `FileUpload` forward refs
|
|
45
|
+
to their actual inputs, not their label wrappers. Use normal React
|
|
46
|
+
`value`/`defaultValue` or `checked`/`defaultChecked` and `onChange` for native
|
|
47
|
+
controls. `Button` defaults to `type="button"`; explicitly opt into form submit.
|
|
48
|
+
|
|
49
|
+
Labels, hints and errors are renderable React content. Hints/errors are associated
|
|
50
|
+
with the control and errors set `aria-invalid`. Required native controls retain
|
|
51
|
+
browser constraint validation. `Field` provides label/description context for one
|
|
52
|
+
control; use the same `controlId` and input `id` if choosing your own identifier.
|
|
53
|
+
Use native `fieldset` and `legend` for related checkbox/radio groups.
|
|
54
|
+
|
|
55
|
+
Set `dir` and `lang` independently at the document or subtree. Horizontal Tabs
|
|
56
|
+
follow computed direction; vertical arrows stay vertical. Theme, mode and density
|
|
57
|
+
are CSS attributes on an ancestor:
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<div dir="rtl" lang="ar" data-hw-theme="dga"
|
|
61
|
+
data-hw-mode="dark" data-hw-density="comfortable">…</div>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Default auxiliary labels are English; provide Arabic or another language through
|
|
65
|
+
label/message props. Business dates and numbers can use `@hawiyah/core` formatters
|
|
66
|
+
with explicit locale, calendar and time zone. No component infers locale from RTL.
|
|
67
|
+
|
|
68
|
+
## Catalog
|
|
69
|
+
|
|
70
|
+
| Component | Composition and important props |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `Button` | Native button; `variant="primary\|secondary\|ghost\|danger"`, `size="sm\|md\|lg"`, `loading` disables and sets busy. |
|
|
73
|
+
| `Field` | `label`, `hint`, `error`, `required`, `controlId`; wrap one form control as children. |
|
|
74
|
+
| `TextField` | Native input attributes plus `label`, `hint`, `error`; supports text/email/date/number/etc. |
|
|
75
|
+
| `Textarea` | Native textarea plus label/hint/error. |
|
|
76
|
+
| `Select` | Native select plus label/hint/error; `options: Option[]` or native option/optgroup children. Native `multiple` is supported. |
|
|
77
|
+
| `Checkbox` | Native checkbox plus label/hint/error and `indeterminate`. |
|
|
78
|
+
| `Radio` | Native radio plus label/hint/error; supply a shared `name` for a native group. |
|
|
79
|
+
| `Switch` | Native checkbox with `role="switch"`, label/hint/error. |
|
|
80
|
+
| `Tabs` | `items: {value,label,content,disabled?}[]`, required `label`, `value`/`defaultValue`, `onValueChange`, `orientation`, `activationMode`, `overflow: menu/scroll` (default menu), configurable `overflowLabel`. Horizontal compact containers move excess labels into a keyboard-accessible disclosure; vertical tabs remain visible. |
|
|
81
|
+
| `Dialog` | Required `title`; `description`, `trigger`, `open`/`defaultOpen`, `onOpenChange`, `closeLabel`, `closeOnBackdrop`; children/footer can render from `{close}`. |
|
|
82
|
+
| `Combobox` | Single selection from `Option[]`; label/hint/error, `value`/`defaultValue`, `onValueChange(value, option?)`, `onInputChange(query)`, `open`/`defaultOpen`, `onOpenChange`, native form attributes. |
|
|
83
|
+
| `Accordion` | `items: {value,title,content,open?,defaultOpen?,onOpenChange?}[]`; `exclusive` uses a native details name group. |
|
|
84
|
+
| `Card` | Native article; header/footer slots and body children. |
|
|
85
|
+
| `Badge` | Static label; `tone="neutral\|success\|warning\|danger\|info"`, `variant="soft\|outline\|dot"`; [source and adaptations](../../docs/nic-badges.md). |
|
|
86
|
+
| `Alert` | `tone="info\|success\|warning\|danger"`, optional text `title`, children. Default role is status (danger: alert); override role for static content. |
|
|
87
|
+
| `Table<Row>` | `caption`, `columns: {key,header,cell(row,index),rowHeader?}[]`, `rows`, `rowKey`, `wrapperProps`; alternatively native table children. |
|
|
88
|
+
| `Pagination` | `totalPages`, `page`/`defaultPage`, `onPageChange`; Arabic default `label`, `previousLabel`, `nextLabel`, `getPageLabel`, `formatPage`; `siblingCount` (default 1), `disabled`, `hideOnSinglePage` (default false). Ellipsis disclosures use `getGapLabel(start,end)`, `jumpLabel`, `goLabel`; gaps above 100 pages use bounded integer entry. Parent fetches/slices data; no navigation or scrolling is imposed. |
|
|
89
|
+
| `Breadcrumb` | `items: {label,href?,current?}[]`, localized `label`; last item is current. |
|
|
90
|
+
| `Progress` | Native progress with required accessible `label`, `value`, `max` (100); omit value for indeterminate. |
|
|
91
|
+
| `Skeleton` | Decorative span, hidden from assistive technology; set dimensions via className/style. |
|
|
92
|
+
| `Spinner` | Status span; localized `label` (default “Loading”). |
|
|
93
|
+
| `Avatar` | Required `name`; optional `src`, `initials`, `size="40\|64\|80\|120\|sm\|md\|lg\|xl"`, `variant="circle\|square"`. Failed images fall back to initials; changing `src` retries. [Source notes](../../docs/nic-avatars.md). |
|
|
94
|
+
| `Divider` | Native horizontal rule. |
|
|
95
|
+
| `Tooltip` | Plain string `content`; one focusable React element as children. |
|
|
96
|
+
| `FileUpload` | Native file input with label/hint/error; `accept`, `multiple`, native `onChange`, `onFilesChange(File[])`, optional supplementary children. |
|
|
97
|
+
| `Stepper` | `items: {value,label,description?,status?}[]`, `current`, accessible `label`. Status: complete/current/upcoming. Static progress, not navigation. |
|
|
98
|
+
| `EmptyState` | Required `title`; optional `description`, decorative `icon`, `action`, children. |
|
|
99
|
+
|
|
100
|
+
All prop interfaces, `TabItem`, `AccordionItem`, `TableColumn<Row>`,
|
|
101
|
+
`BreadcrumbItem`, `StepItem`, and core `Option`, `Direction`, `Orientation` types
|
|
102
|
+
are exported. Option values and item values must be unique stable strings.
|
|
103
|
+
|
|
104
|
+
## Stateful controls
|
|
105
|
+
|
|
106
|
+
### Tabs
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<Tabs
|
|
110
|
+
label="Application sections"
|
|
111
|
+
value={section}
|
|
112
|
+
onValueChange={setSection}
|
|
113
|
+
activationMode="manual"
|
|
114
|
+
items={[
|
|
115
|
+
{ value: 'details', label: 'Details', content: <Details /> },
|
|
116
|
+
{ value: 'history', label: 'History', content: <History /> },
|
|
117
|
+
]}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Arrows wrap and skip disabled items; Home/End move to the first/last enabled tab.
|
|
122
|
+
Automatic activation (default) selects while moving focus. Manual activation
|
|
123
|
+
selects through the native button's Enter/Space/click behavior. Inactive panels
|
|
124
|
+
stay mounted with `hidden`, preserving their form state. The first enabled tab
|
|
125
|
+
is the default and the fallback if the supplied selection is unavailable.
|
|
126
|
+
|
|
127
|
+
### Dialog
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<Dialog title="Review request" trigger={<Button>Review</Button>}
|
|
131
|
+
footer={({ close }) => <Button onClick={close}>Done</Button>}>
|
|
132
|
+
{({ close }) => <p>Review your details before continuing.</p>}
|
|
133
|
+
</Dialog>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The wrapper invokes native `showModal()` and `close()`; it requires native modal
|
|
137
|
+
dialog support. Native modality contains focus and makes the background inert.
|
|
138
|
+
Escape requests closing; set `onCancel={event => event.preventDefault()}` to
|
|
139
|
+
cancel that action. Backdrop closing defaults on and can be disabled.
|
|
140
|
+
`autoFocus` on a child selects initial focus. Closing restores the prior focused
|
|
141
|
+
element when it remains connected. The optional trigger is one button-like React
|
|
142
|
+
element that forwards `onClick`; its original handler runs first and can prevent
|
|
143
|
+
opening. You can also use a separate button with controlled `open`.
|
|
144
|
+
|
|
145
|
+
Server rendering emits a closed dialog; a default-open dialog becomes modal after
|
|
146
|
+
hydration. For controlled state, handle `onOpenChange` to apply requests from the
|
|
147
|
+
close button, Escape or native dialog forms.
|
|
148
|
+
|
|
149
|
+
### Combobox
|
|
150
|
+
|
|
151
|
+
The editable single-select input shares `transitionCombobox` and
|
|
152
|
+
`getComboboxOptions` with other adapters. Arabic diacritics/alef variants and
|
|
153
|
+
letter case are folded for searching, without changing labels or stored values.
|
|
154
|
+
Opening a committed selection displays all options. Typing clears the committed
|
|
155
|
+
selection; arrows/Home/End change the active option, and Enter or pointer click
|
|
156
|
+
commits an enabled option. Focus stays in the input. Escape/Tab close the list;
|
|
157
|
+
blur keeps the query without silently selecting.
|
|
158
|
+
|
|
159
|
+
`name` belongs to a hidden native input containing the selected option value.
|
|
160
|
+
Arbitrary text does not become a submitted value. `required` uses custom validity
|
|
161
|
+
to require a committed choice; localize its message with `requiredMessage`.
|
|
162
|
+
`disabled`, `readOnly`, `form`, forwarded input refs, and native form resets are
|
|
163
|
+
supported. A reset restores an uncontrolled `defaultValue`; controlled state
|
|
164
|
+
continues to belong to the caller. When controlled, apply `onValueChange`, including
|
|
165
|
+
its empty string when the user edits the selection.
|
|
166
|
+
|
|
167
|
+
Use `getResultsMessage(count)` for the live region and `emptyMessage` for the
|
|
168
|
+
empty list. There is no multiselect, remote fetching, option virtualization, or
|
|
169
|
+
custom option rendering in this version. The caller can supply updated options.
|
|
170
|
+
|
|
171
|
+
### Tooltip and file upload
|
|
172
|
+
|
|
173
|
+
Tooltip adds a description to its focusable child, opens on hover/focus, and closes
|
|
174
|
+
on Escape or when focus/pointer leave. Custom child components must forward
|
|
175
|
+
`aria-describedby`. Keep tooltip text noninteractive; essential instructions belong
|
|
176
|
+
in visible labels/hints. FileUpload is a native file picker. It does not upload,
|
|
177
|
+
validate file contents, or create network requests.
|
|
178
|
+
|
|
179
|
+
## Example and checks
|
|
180
|
+
|
|
181
|
+
`examples/react` is a complete local service application: conditional applicant
|
|
182
|
+
fields, Arabic city search, review dialog, request history/filter/pagination,
|
|
183
|
+
independent locale/direction/mode toggles and a service guide. Its sample requests
|
|
184
|
+
are ephemeral in-memory data. Build the workspace packages, then run Vite using
|
|
185
|
+
`examples/react/vite.config.ts` on port 4174.
|
|
186
|
+
|
|
187
|
+
Focused tests cover import/server rendering without DOM globals, field/ref/form
|
|
188
|
+
associations, RTL/manual/controlled tabs, Arabic combobox search and commits,
|
|
189
|
+
controlled typing, reset, modal lifecycle calls, tooltip dismissal and bounded
|
|
190
|
+
pagination. JSDOM dialog methods are test doubles; native modality and browser
|
|
191
|
+
focus containment need the browser integration suite.
|
|
192
|
+
|
|
193
|
+
## Expanded catalog: 50 additional components
|
|
194
|
+
|
|
195
|
+
The package now exports 77 components. Added components use the same native
|
|
196
|
+
attributes/ref conventions and shared styles. Array values and item identifiers
|
|
197
|
+
must be unique. Custom form controls support `value`/`defaultValue` and
|
|
198
|
+
`onValueChange`; uncontrolled values return to their defaults on native form reset,
|
|
199
|
+
including forms associated through `form`. Canceled reset events are respected.
|
|
200
|
+
Controlled values remain owned by the application.
|
|
201
|
+
|
|
202
|
+
| Added control | API and behavior |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| `InputGroup` | `start`/`end` adornments and control children; surrounding `Field` supplies the accessible label. |
|
|
205
|
+
| `PasswordField` | TextField props plus `visible`/`defaultVisible`, `onVisibleChange`, `showLabel`, `hideLabel`. Reveal preserves the native input and its value. |
|
|
206
|
+
| `SearchField` | String `value/defaultValue`, `onValueChange`, native `onChange`, `clearLabel`; optional `suggestions`, `maxSuggestions` (8), `resultsMessage(count)`, `onSearch(query)`, `showSearchButton` (false), `searchLabel`. Native input props/ref and field decoration are preserved. |
|
|
207
|
+
| `NumberField` | Native number input with label/hint/error, min/max/step and normal React input events. Empty remains empty; it is not coerced to zero. |
|
|
208
|
+
| `Slider` | Numeric value/defaultValue, `onValueChange`, min/max/step, `showValue`, `formatValue`; one labelled native range. |
|
|
209
|
+
| `RangeSlider` | Numeric `[lower,upper]`, `onValueChange`, min/max/step; required `lowerLabel`/`upperLabel`, optional group `label`. `lowerName`/`upperName` or repeated `name` submit both values. Native handles cannot cross. |
|
|
210
|
+
| `Rating` | Numeric value/defaultValue, `onValueChange`, max (1–20, default 5), label/name/required, `getRatingLabel`; one native radio group. |
|
|
211
|
+
| `RatingDisplay` | Required `label`, numeric `value=0`, `max=5` (1–20), `showValue=true`, `getValueLabel(value,max)`; noninteractive fractional aggregate score with one accessible image name. |
|
|
212
|
+
| `PinInput` | String value/defaultValue, `onValueChange`, `length` (default 6), optional decorative `showSlots`; one accessible OTP input normalizes Arabic-Indic and Eastern Arabic digits, including pasted input. |
|
|
213
|
+
| `TagInput` | String array value/defaultValue, `onValueChange`, name, required, `getRemoveLabel`, `requiredMessage`; Enter/comma commits a unique tag, empty Backspace removes the last tag. Each committed tag produces a native form value. |
|
|
214
|
+
| `MultiSelect` | Required label and options; string array value/defaultValue, `onValueChange`, name, required, `searchLabel`, `emptyMessage`, `requiredMessage`. Searchable native checkboxes; filtered-out selections retain repeated form values. |
|
|
215
|
+
| `Calendar` | ISO Gregorian value/defaultValue, `onValueChange`; month/defaultMonth, `onMonthChange`; locale/calendar/weekStartsOn, min/max, `isDateDisabled`, disabled/readOnly, optional form/name and localized toolbar/day labels. |
|
|
216
|
+
| `DatePicker` | Typed ISO text input plus Calendar in a native modal. Adds calendar/defaultCalendar, `onCalendarChange`, localized calendar selector labels, calendar button/dialog labels and unsupported-range message. |
|
|
217
|
+
| `FileDropzone` | Native file input props plus `onFilesChange(File[])`, `dropLabel`, `getRejectedMessage`; accepted dropped files populate the actual native input. The picker and dropped selection participate in forms. No upload occurs automatically. |
|
|
218
|
+
|
|
219
|
+
Native `TextField` input types retain their platform semantics: text/search/tel/url
|
|
220
|
+
are strings; email uses native validation; number uses native numeric constraints
|
|
221
|
+
and permits empty input; date/month/week/time/datetime-local use HTML's date/time
|
|
222
|
+
value formats; color uses the native picker. Use `FileUpload`/`FileDropzone` for
|
|
223
|
+
file values, Checkbox/Radio/Switch for checked state, and Slider/RangeSlider for
|
|
224
|
+
range controls. A native date input stores Gregorian ISO dates regardless of the
|
|
225
|
+
calendar used to select or describe a date.
|
|
226
|
+
|
|
227
|
+
### Saudi date selection
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
const [date, setDate] = useState('2026-10-28');
|
|
231
|
+
const [calendar, setCalendar] = useState<'gregory' | 'islamic-umalqura'>('islamic-umalqura');
|
|
232
|
+
|
|
233
|
+
<DatePicker
|
|
234
|
+
label="تاريخ الموعد"
|
|
235
|
+
name="appointment"
|
|
236
|
+
value={date}
|
|
237
|
+
onValueChange={setDate}
|
|
238
|
+
calendar={calendar}
|
|
239
|
+
onCalendarChange={setCalendar}
|
|
240
|
+
locale="ar-SA"
|
|
241
|
+
calendarSystemLabel="التقويم"
|
|
242
|
+
gregorianLabel="ميلادي"
|
|
243
|
+
hijriLabel="هجري — أم القرى"
|
|
244
|
+
calendarLabel="اختر تاريخ الموعد"
|
|
245
|
+
buttonLabel="فتح التقويم"
|
|
246
|
+
previousLabel="الشهر السابق"
|
|
247
|
+
nextLabel="الشهر التالي"
|
|
248
|
+
closeLabel="إغلاق"
|
|
249
|
+
required
|
|
250
|
+
/>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The picker includes a Gregorian/Umm al-Qura selector. Switching display systems
|
|
254
|
+
preserves the exact ISO day, and reopening returns to the selected date's month.
|
|
255
|
+
Calendar names, navigation, picker controls and validation messages default to Arabic. Set `locale="en"` for English copy or pass a label prop to override a particular control.
|
|
256
|
+
|
|
257
|
+
Direction and locale remain independent of calendar. Calendar's arrows follow
|
|
258
|
+
visual RTL/LTR direction; Up/Down move a week, Home/End move within the week,
|
|
259
|
+
PageUp/PageDown move a month, and Shift+PageUp/PageDown move a year. Disabled days
|
|
260
|
+
are skipped and focus remains on one roving date button.
|
|
261
|
+
|
|
262
|
+
Umm al-Qura arithmetic and numeric date labels use the shared Saudi reference
|
|
263
|
+
table through `@hawiyah/core`, including `formatCalendarDate`; they do not rely on
|
|
264
|
+
ICU's differing historical/future numeric Hijri fields. The supported table spans
|
|
265
|
+
**1924-08-01 through 2077-11-16 (AH 1343–1500)**. Navigation stops at these
|
|
266
|
+
boundaries. When a Gregorian selected date lies outside this range, switching to
|
|
267
|
+
Hijri preserves the ISO input, shows a localized unsupported-range message, and
|
|
268
|
+
renders no fabricated Hijri selection, and blocks native form submission with custom validity and `aria-invalid`. Switching back to Gregorian clears the calendar-range error while keeping application min/max constraints. Use `unsupportedCalendarMessage` to
|
|
269
|
+
translate that explanation. Read the workspace calendar evidence for provenance
|
|
270
|
+
and verification; this interface is not an official service or certification.
|
|
271
|
+
|
|
272
|
+
`getDayLabel` customizes Calendar date announcements. Supply stable initial
|
|
273
|
+
`month`/`defaultMonth` or `value` when a server-rendered view must be independent of
|
|
274
|
+
the current date. Standalone Calendar submits its selected supported date through
|
|
275
|
+
an optional hidden `name`; use DatePicker when native required/date validation is
|
|
276
|
+
needed. `isDateDisabled` applies to both the calendar and the DatePicker's native
|
|
277
|
+
input validation. `unavailableMessage` localizes custom date validation.
|
|
278
|
+
|
|
279
|
+
| Added interaction | API and behavior |
|
|
280
|
+
| --- | --- |
|
|
281
|
+
| `ToggleGroup` | Required label/options, `variant="segmented\|outline"`. Default single selection uses native radios with string value; `multiple` uses pressed buttons with string-array value and repeated hidden form values. Both support defaultValue/onValueChange/name/form/disabled/readOnly. |
|
|
282
|
+
| `Popover` | Required title/trigger, open/defaultOpen/onOpenChange and region children. Trigger toggles a labelled disclosure; outside press and Escape close. Interactive content uses ordinary Tab. |
|
|
283
|
+
| `Menu` | Required trigger/label and `items: {value,label,disabled?,href?,onSelect?}[]`; open/defaultOpen/onOpenChange and `onAction(value)`. Up/Down/Home/End skip disabled entries; Escape/action return focus. |
|
|
284
|
+
| `Drawer` | Dialog props plus `side="start\|end\|bottom"`; same native modal and focus behavior as Dialog. |
|
|
285
|
+
| `ToastRegion` | `messages: {id,title?,description,tone?,urgent?,dismissible?}[]`, `onDismiss(id)`, `label`, `getDismissLabel(message)`. Choose `variant="banner"` and optionally `position="inline"` or a corner. Buttons require an `onDismiss` handler. Arabic labels default to الإشعارات and إغلاق الإشعار with available message text. |
|
|
286
|
+
| `Collapsible` | Native details with title, open/defaultOpen/onOpenChange, disabled and children. |
|
|
287
|
+
| `TreeView` | Required label and `items: {id,label,disabled?,children?}[]`; value/defaultValue/onValueChange and expanded/defaultExpanded/onExpandedChange. Visible nodes have tree levels, positions and roving focus; horizontal expansion follows RTL. |
|
|
288
|
+
| `Carousel` | Required label/slides; `index/defaultIndex/onIndexChange`, `loop=false`, renderable `slides`, zero-based `getSlideLabel(index,total)`. `showIndicators=true`, localized control/indicator/description/empty labels, inert inactive slides, explicit navigation and no autoplay. [Source and motion notes](../../docs/nic-carousel.md). |
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
// Toast state is ordinary application state. There is no global singleton.
|
|
292
|
+
const [messages, setMessages] = useState([
|
|
293
|
+
{ id: 'saved', description: 'تم حفظ المسودة', tone: 'success' as const },
|
|
294
|
+
]);
|
|
295
|
+
<ToastRegion label="الإشعارات" messages={messages}
|
|
296
|
+
getDismissLabel={() => 'إغلاق الإشعار'}
|
|
297
|
+
onDismiss={id => setMessages(current => current.filter(item => item.id !== id))} />
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Popover/Menu trigger elements must forward native button event and ARIA props.
|
|
301
|
+
TreeView is a single-selection navigation structure, without drag/drop or virtual
|
|
302
|
+
rows. Caller-owned items and toast messages remain unchanged until the caller
|
|
303
|
+
applies a callback.
|
|
304
|
+
|
|
305
|
+
| Added content/pattern | API and behavior |
|
|
306
|
+
| --- | --- |
|
|
307
|
+
| `Link` | Native anchor with optional `external` (new tab and noopener/noreferrer). |
|
|
308
|
+
| `IconButton` | Button props plus required accessible `label`; icon children are decorative. |
|
|
309
|
+
| `ButtonGroup` | Native group with required accessible `label` and button children. |
|
|
310
|
+
| `Chip` | Text children, optional tone/onRemove/removeLabel/disabled. |
|
|
311
|
+
| `DescriptionList` | `items: {term,description,key?}[]`; native dl/dt/dd. |
|
|
312
|
+
| `Stat` | Required label/value; optional description/trend content. Values are formatted by the caller. |
|
|
313
|
+
| `Timeline` | `items: {id,title,description?,dateTime?,dateLabel?,status?}[]`; status complete/active/upcoming and optional label. |
|
|
314
|
+
| `Meter` | Native meter attributes with required accessible label. |
|
|
315
|
+
| `AvatarGroup` | Required items/label, max (default 5), getOverflowLabel. Items use AvatarProps. |
|
|
316
|
+
| `DataTable<Row>` | Required caption/rows/columns; columns have key/label/sortable/render/rowHeader. Optional rowKey, sort/defaultSort/onSortChange, locale, emptyMessage, getSortLabel. Stable immutable localized sorting and native aria-sort headers. |
|
|
317
|
+
| `ServiceCard` | Required title; description/category/icon/metadata, href/actionLabel or action slot, body children. |
|
|
318
|
+
| `ServiceDetails` | Required title; description/metadata/requirements/requirementsLabel/action and children. |
|
|
319
|
+
| `PortalHeader` | Required brand slot, optional brandHref/navigation/navigationLabel/actions/notice and children. Navigation items are label/href/current. Optional top-level `groups` contain a label and child links. See [grouped navigation](../../docs/nic-portal-navigation.md). |
|
|
320
|
+
| `PortalFooter` | Optional brand/description/links/linksLabel/legal and children. |
|
|
321
|
+
| `Feedback` | Required question label; value/defaultValue/onValueChange for `{helpful:'yes'\|'no'\|'',comment}` and `onFeedback` on native submit; translated yes/no/comment/submit/success labels. |
|
|
322
|
+
| `CookieConsent` | Required title/description; value/defaultValue/onValueChange (`accepted`/`rejected`/null), translated buttons and optional policy link. Null displays the notice. Persistence and cookie activation belong to the application. |
|
|
323
|
+
| `NotificationList` | Required label/items; items id/title/description/href/dateTime/dateLabel/read. Optional emptyMessage, onMarkRead, getMarkReadLabel, unreadLabel. |
|
|
324
|
+
|
|
325
|
+
Platform patterns are configurable ordinary content. Supply your own brand,
|
|
326
|
+
service facts, legal text and links. They do not provide government seals, verified
|
|
327
|
+
trust status, identity verification, authentication, submissions or storage.
|
|
328
|
+
Feedback callbacks report local user choices; applications own asynchronous
|
|
329
|
+
submission outcomes. DataTable provides native sorting, without editing,
|
|
330
|
+
virtualization, selection or a remote data engine; existing Table remains fully
|
|
331
|
+
composable for those integrations.
|
|
332
|
+
|
|
333
|
+
### Layout primitives
|
|
334
|
+
|
|
335
|
+
| Primitive | Native composition |
|
|
336
|
+
| --- | --- |
|
|
337
|
+
| `Container` | Div with optional maxWidth. |
|
|
338
|
+
| `Stack` | Vertical flex div. |
|
|
339
|
+
| `Inline` | Horizontal flex div with optional wrap. |
|
|
340
|
+
| `Grid` | Div with responsive columns or minItemWidth. |
|
|
341
|
+
| `Columns` | Div with responsive explicit columns. |
|
|
342
|
+
| `Sidebar` | Two child areas; side/sidebarWidth/collapseAt control responsive placement. |
|
|
343
|
+
| `Center` | Centered content div. |
|
|
344
|
+
| `Spacer` | Flexible space div. |
|
|
345
|
+
| `AspectRatio` | Div with positive numeric ratio. |
|
|
346
|
+
| `Section` | Semantic section with common layout props. |
|
|
347
|
+
| `AppShell` | Supply `header`, `sidebar` and `footer` content around the main landmark. The Arabic skip link focuses main. Set `mainId` to choose its target ID and `skipLabel` to localize the link. |
|
|
348
|
+
| `PageHeader` | Native header with title h1, description/breadcrumb/actions and children. |
|
|
349
|
+
|
|
350
|
+
The first ten primitives accept shared `LayoutProps` and native attributes/refs.
|
|
351
|
+
`gap` and `padding` accept token numbers 0–16 or CSS lengths, including responsive
|
|
352
|
+
objects `{base,sm,md,lg,xl}`. `columns` accepts positive integer values or the same
|
|
353
|
+
responsive object. Common props also include align, justify and wrap. Styles come
|
|
354
|
+
from `layoutStyles` CSS variables; there are no JS viewport measurements. Consumer
|
|
355
|
+
`style` overrides can explicitly replace generated properties.
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
<Container maxWidth="76rem" padding={{ base: 4, lg: 8 }}>
|
|
359
|
+
<Stack gap={6}>
|
|
360
|
+
<PageHeader title="الخدمات" description="اختر الخدمة المناسبة" />
|
|
361
|
+
<Sidebar side="start" sidebarWidth="18rem" collapseAt="md" gap={6}>
|
|
362
|
+
<aside>مرشحات الخدمات</aside>
|
|
363
|
+
<Grid columns={{ base: 1, md: 2, xl: 3 }} gap={4}>
|
|
364
|
+
<ServiceCard title="تصريح نشاط" href="/services/permit" actionLabel="تفاصيل الخدمة" />
|
|
365
|
+
</Grid>
|
|
366
|
+
</Sidebar>
|
|
367
|
+
</Stack>
|
|
368
|
+
</Container>
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Integration boundaries and evidence
|
|
372
|
+
|
|
373
|
+
Maps, rich-text editors, charts, code editors, PDF viewers, CAPTCHA and payment
|
|
374
|
+
engines belong to their specialist libraries/services. Mount the real engine in
|
|
375
|
+
an ordinary React-owned region or Card/AspectRatio with its own accessible name,
|
|
376
|
+
loading/error UI and lifecycle cleanup. Use Field hint/error associations around
|
|
377
|
+
real input engines and Dialog only when an engine's focus model supports native
|
|
378
|
+
modality. Pass theme tokens/direction through the engine's documented API, use
|
|
379
|
+
its documented ref/event integration, and adapt actual resulting values into your
|
|
380
|
+
form state. These components do not simulate an engine, credential exchange or
|
|
381
|
+
payment outcome, and do not inject unsafe HTML.
|
|
382
|
+
|
|
383
|
+
Expansion regressions cover all 50 additions under DOM-free server rendering,
|
|
384
|
+
responsive CSS-variable output, PIN digit normalization, repeated values and
|
|
385
|
+
external/canceled resets, ordered range handles, Saudi calendar navigation and
|
|
386
|
+
range boundaries, picker system switching/reopening/unsupported dates, menu and
|
|
387
|
+
tree focus, popover dismissal, table sorting, caller-owned toasts and explicit
|
|
388
|
+
feedback/consent callbacks. Native dialog modality and browser accessibility
|
|
389
|
+
remain covered by the existing browser suite; server/unit tests are not a claim
|
|
390
|
+
of complete assistive-technology testing for every new pattern.
|
|
391
|
+
|
|
392
|
+
## Portal shell
|
|
393
|
+
|
|
394
|
+
[`PortalLayout`, `PortalHeader` and `SecondaryNav`](PORTAL.md) provide a complete
|
|
395
|
+
Arabic-default portal shell with responsive navigation, breadcrumbs and footer.
|
|
396
|
+
Run the React example with `?preview=portal` to use the native composed shell.
|
|
397
|
+
|
|
398
|
+
## NIC card composition
|
|
399
|
+
|
|
400
|
+
See [cards](../../docs/nic-cards.md) for source-mapped spacing, variants, whole-card links, disabled semantics and content classes. Native framework consumers include `?preview=nic`; vanilla uses the documented semantic HTML recipe.
|
|
401
|
+
|
|
402
|
+
See [NIC button variants](../../docs/nic-buttons.md) for all ten appearances,
|
|
403
|
+
interaction states, dark-surface use and density adaptations.
|
|
404
|
+
|
|
405
|
+
[Ready component examples](../../docs/ready-component-examples.md) cover all five
|
|
406
|
+
alert/notification tones, header/footer composition and guide-only navigation containment.
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
[Site verification](../../docs/site-verification.md) composes a native disclosure above the header with deployment-owned domain and certificate information. [Grouped portal footers](../../docs/nic-footer.md) add navigation groups, support actions, legal links and identity slots.
|
|
410
|
+
|
|
411
|
+
[Link and breadcrumb states](../../docs/nic-links.md) document neutral/standalone variants, disabled destinations, source contrast substitutions and native adapter APIs.
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
### Table presentation and empty results
|
|
415
|
+
|
|
416
|
+
`Table` and `DataTable` expose `variant="default|striped|bordered"`,
|
|
417
|
+
`size="sm|md|lg"` and `emptyMessage`. DGA cells have a 48px default minimum;
|
|
418
|
+
40px/56px alternate sizes and striped/bordered variants are Hawiyah extensions.
|
|
419
|
+
Captions name keyboard-focusable horizontal scroll containers; row-header
|
|
420
|
+
columns render native `th scope="row"`. Empty data spans the column count and
|
|
421
|
+
uses an Arabic message by default. Sorting does not mutate caller records.
|
|
422
|
+
React/Vue native `data-variant` and `data-size` attributes remain supported;
|
|
423
|
+
typed props take precedence. `wrapperProps` customizes the scroll container.
|
|
424
|
+
See [table evidence and adaptations](../../docs/nic-tables.md).
|
|
425
|
+
|
|
426
|
+
Rating inputs select whole numbers; finite prefilled values are clamped to the normalized maximum and floored. Fractional averages belong in `RatingDisplay`. Nonfinite maxima fall back to 5 and nonfinite values to 0. Arabic labels and Latin digits are the defaults.
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
### Search suggestions
|
|
430
|
+
|
|
431
|
+
SearchField accepts local string suggestions and remains a free-text input.
|
|
432
|
+
With suggestions supplied it exposes an editable combobox/listbox, highlighted
|
|
433
|
+
matches and a polite result count. Arrow keys wrap through matches; Enter on an
|
|
434
|
+
active suggestion selects it and prevents form submission. Ordinary Enter with
|
|
435
|
+
no active suggestion emits `onSearch` with a trimmed, nonempty query and keeps
|
|
436
|
+
native form submission available. Choose either the search callback or the
|
|
437
|
+
form's submit handler for the application request; wiring both duplicates it.
|
|
438
|
+
The optional icon search action is a non-submit button and uses the callback.
|
|
439
|
+
Arabic clear/search labels are defaults and can be localized.
|
|
440
|
+
|
|
441
|
+
Escape dismisses an open list before reaching an enclosing dialog; another
|
|
442
|
+
Escape can dismiss the dialog. Composition/modifier keys do not commit matches.
|
|
443
|
+
Readonly inputs remain searchable but cannot edit/clear/select suggestions;
|
|
444
|
+
disabled inputs cannot search. Blur, outside press, reset and changed suggestion
|
|
445
|
+
configuration clear active-option state. No remote search service is called.
|
|
446
|
+
|
|
447
|
+
### Content navigation
|
|
448
|
+
|
|
449
|
+
`ContentNavigation` follows application-owned section IDs using nested
|
|
450
|
+
`items: {id, label, disabled?, children?}[]`. Options are `label` (Arabic default),
|
|
451
|
+
`showHeading` (true), `sticky` (false), `scrollRoot` (null/window) and `offset`
|
|
452
|
+
(80px). `onCurrentChange(id)` reports the current section ID. Ordinary
|
|
453
|
+
activation scrolls without changing the URL; keyboard activation also focuses
|
|
454
|
+
the target. Modified anchor clicks retain browser behavior. Disabled entries
|
|
455
|
+
remain noninteractive text links; no section content is created or hidden.
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
import {ContentNavigation} from '@hawiyah/react';
|
|
459
|
+
|
|
460
|
+
<ContentNavigation items={[{id: 'requirements', label: 'المتطلبات'}]} />
|
|
461
|
+
<section id="requirements"><h2>المتطلبات</h2></section>
|
|
462
|
+
```
|