Initial Commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# `<ShareDialog />`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`<ShareDialog />` renders the modal sharing UI for a partition. It
|
||||
exposes a recipients list, an add-recipient form (text input plus
|
||||
permission select), and a revoke button per row. The component is
|
||||
controlled — `open`, `recipients`, `loading`, and `errorMessage` are
|
||||
all owned by the parent. Wire it to `useSharing` for live engine
|
||||
integration or hand it static props in Storybook.
|
||||
|
||||
## Features
|
||||
|
||||
- Controlled `open` prop — renders `null` when closed so callers can
|
||||
conditionally mount.
|
||||
- Focus moves to the recipient input on open.
|
||||
- ESC key closes the dialog. Backdrop click also closes; clicks
|
||||
inside the dialog do NOT close (stopPropagation).
|
||||
- ARIA: `role="dialog"`, `aria-modal="true"`, `aria-labelledby` tied to
|
||||
the title heading. Error region uses `role="alert"`.
|
||||
- Recipient list reuses the same `data-grant-id` row contract as
|
||||
`<FileAccessList />`.
|
||||
- Localisable: pass `labels` to override every string. Permission
|
||||
options localise individually.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```tsx
|
||||
import { ShareDialog } from "@suaveplan/drive-react-sharing";
|
||||
import { useState } from "react";
|
||||
|
||||
function Trigger() {
|
||||
const sharing = useSharing(/* ... */);
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<button type="button" onClick={() => setOpen(true)}>Share</button>
|
||||
<ShareDialog
|
||||
open={open}
|
||||
recipients={sharing.recipients}
|
||||
onAdd={(id, p) => sharing.addRecipient(id, p)}
|
||||
onRemove={(id) => sharing.removeRecipient(id)}
|
||||
onClose={() => setOpen(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
Custom labels for a localised application:
|
||||
|
||||
```tsx
|
||||
<ShareDialog
|
||||
open={open}
|
||||
recipients={sharing.recipients}
|
||||
loading={sharing.loading}
|
||||
errorMessage={sharing.error?.message}
|
||||
defaultPermission="write"
|
||||
onAdd={(id, p) => sharing.addRecipient(id, p)}
|
||||
onRemove={(id) => sharing.removeRecipient(id)}
|
||||
onClose={() => setOpen(false)}
|
||||
labels={{
|
||||
title: "Partager",
|
||||
add: "Ajouter",
|
||||
revoke: "Révoquer",
|
||||
empty: "Aucun destinataire",
|
||||
permissionOptions: {
|
||||
read: "Lecture",
|
||||
write: "Écriture",
|
||||
delete: "Suppression",
|
||||
share: "Partage",
|
||||
admin: "Administrateur",
|
||||
},
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `ShareDialogProps`:
|
||||
- `open: boolean` — required.
|
||||
- `recipients: readonly ShareRecipient[]` — required.
|
||||
- `onAdd(recipientId, permission): void | Promise<void>` — required.
|
||||
- `onRemove(grantId): void | Promise<void>` — required.
|
||||
- `onClose(): void` — required.
|
||||
- `title?: string` — overrides `labels.title`.
|
||||
- `loading?: boolean` — disables interactive controls.
|
||||
- `errorMessage?: string` — renders `role="alert"` banner.
|
||||
- `defaultPermission?: SharePermission` — initial select value.
|
||||
- `labels?: Partial<ShareDialogLabels>` — string overrides.
|
||||
- `ShareDialogLabels` — exported interface; permission options
|
||||
override individually.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The dialog is intentionally a controlled component because the open
|
||||
state is usually tied to other UI in the parent (an avatar stack, a
|
||||
"Share" button, a routing flag). Storybook can drive the entire surface
|
||||
with mocked callbacks. The error region is rendered only when
|
||||
`errorMessage` is a non-empty string — passing an undefined or
|
||||
zero-length string hides it. The submit button is disabled when the
|
||||
recipient draft is empty so users cannot accidentally fire `onAdd`
|
||||
with whitespace.
|
||||
Reference in New Issue
Block a user