Skip to Content
GuidesDSR (Data Subject Request)

DSR — Data Subject Request

The <asiri-dsr> Web Component lets your users submit privacy requests (access, erasure, rectification, portability, restriction, objection) directly from your product. It is dependency-free and works in any framework or plain HTML.


Install

npm / bundler

npm install @asiri-ng/elements # or pnpm add @asiri-ng/elements
import '@asiri-ng/elements/dsr';

CDN (no build step)

<script async src="https://cdn.jsdelivr.net/npm/@asiri-ng/elements@0.1.0/dist/dsr.global.js" ></script>

Quick start

Place the element anywhere in your markup:

<asiri-dsr tenant="YOUR_TENANT_SLUG"></asiri-dsr>

This renders a button that opens a modal dialog when clicked. The form auto-loads your branding (name, logo, primary colour) from the Asiri portal API.


Variants

variantBehaviour
button(default) A trigger button that opens a modal dialog.
inlineThe form renders directly in the page — no modal.
floatingA fixed-position launcher button (bottom-right) → modal.
<!-- Inline form — no modal --> <asiri-dsr tenant="acme" variant="inline"></asiri-dsr> <!-- Floating launcher --> <asiri-dsr tenant="acme" variant="floating" position="bottom-right"></asiri-dsr>

All attributes

AttributeRequiredDefaultDescription
tenantYesYour tenant slug.
api-baseNohttps://api.asiri.ngOverride the API base URL (e.g. staging).
variantNobuttonLayout: button, inline, floating.
themeNolightColour mode: light, dark, auto (follows OS preference).
accentNo#142044Brand accent colour (any CSS colour value).
radiusNomdCorner radius: sm (6 px), md (10 px), lg (14 px), pill.
sizeNomdRelative size: sm, md, lg.
positionNobottom-rightFloating variant anchor: bottom-left/right, top-left/right.
labelNoPrivacy requestTrigger button text.
localeNobrowser defaultBCP 47 locale tag (reserved for future i18n use).
turnstile-site-keyNoCloudflare Turnstile site key — enables captcha on the form.

Request types

The form offers exactly these six request types in the dropdown:

  • Access — access my data
  • Rectification — correct / rectify my data
  • Erasure — erase my data (right to be forgotten)
  • Portability — export / portability
  • Restriction — restrict processing
  • Objection — object to processing

Programmatic mount

import { mountAsiriDsr } from '@asiri-ng/elements/dsr'; mountAsiriDsr({ tenant: 'YOUR_TENANT_SLUG', variant: 'inline', theme: 'auto', target: document.getElementById('dsr-container') ?? undefined, });

Design tokens

Override any token from outside the shadow root:

asiri-dsr { --asiri-dsr-accent: #7c3aed; /* trigger button + focus rings */ --asiri-dsr-bg: #ffffff; /* panel background */ --asiri-dsr-bg-2: #f8fafc; /* secondary background */ --asiri-dsr-text: #101322; /* primary text */ --asiri-dsr-muted: #647084; /* secondary text */ --asiri-dsr-border: #dfe4ee; /* borders */ --asiri-dsr-shadow: 0 22px 64px rgba(16, 24, 40, 0.14); --asiri-dsr-danger: #c0392b; /* validation errors */ --asiri-dsr-success: #2f9b63; /* success state */ --asiri-dsr-font: Inter, sans-serif; --asiri-dsr-radius: 10px; /* corner radius (overridden by `radius` attr) */ }

Token precedence: explicit accent / radius attributes beat CSS token overrides, which beat built-in defaults.


Shadow parts

Style individual pieces with ::part():

asiri-dsr::part(trigger) { /* the launch button */ } asiri-dsr::part(float-button) { /* floating launcher button */ } asiri-dsr::part(dialog) { /* modal container / inline panel */ } asiri-dsr::part(backdrop) { /* semi-transparent overlay */ } asiri-dsr::part(header) { /* panel header row */ } asiri-dsr::part(form) { /* the <form> element */ } asiri-dsr::part(field) { /* each field wrapper */ } asiri-dsr::part(label) { /* field labels */ } asiri-dsr::part(input) { /* text / email inputs */ } asiri-dsr::part(select) { /* dropdowns */ } asiri-dsr::part(textarea) { /* details textarea */ } asiri-dsr::part(submit) { /* submit button */ } asiri-dsr::part(cancel) { /* cancel button */ } asiri-dsr::part(close) { /* × close button */ } asiri-dsr::part(success) { /* success confirmation view */ } asiri-dsr::part(error) { /* error messages */ }

Captcha (Cloudflare Turnstile)

When turnstile-site-key is provided the component:

  1. Lazily injects the Turnstile script from challenges.cloudflare.com (only once per page).
  2. Renders the Turnstile widget inside the form.
  3. Includes the resulting token as captchaToken in the POST body.

If the attribute is omitted the form submits without a captcha token (suitable for internal tools or when server-side rate limiting is sufficient).

<asiri-dsr tenant="acme" turnstile-site-key="0x4AAAAAAA..."></asiri-dsr>

Accessibility

  • Modal uses role="dialog" aria-modal="true" with a labelled title (aria-labelledby).
  • Focus moves to the first field on open; a focus trap keeps Tab cycling within the dialog.
  • Escape and clicking the backdrop both close the modal and restore focus to the trigger.
  • Every field has a <label for> pointing to its id; required fields carry aria-required="true".
  • Invalid fields receive aria-invalid="true" + aria-describedby pointing to the error message.
  • Email input uses type="email" inputmode="email"; phone uses inputmode="tel".
  • All document listeners (Escape, outside-click) are removed in disconnectedCallback — no memory leaks.
  • prefers-color-scheme listener (for theme="auto") is also removed on disconnect.