diff --git a/README.md b/README.md index 6ab3c18..eb02085 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,18 @@ ### JavaScript utility library -- No dependencies -- Choose between `checkbox` or `radio` inputs -- Customizable cookie types (identifiers, optional/required, pre-checked) -- Conditional script tags, iframes and elements based on cookie consent and type +- No dependencies +- Customizable cookie types (identifiers, optional/required, pre-checked) +- Conditional script tags, iframes and elements based on cookie consent and type -Screenshot of the GDPR proof cookie consent dialog from @grrr/cookie-consent with checkbox inputsScreenshot of the GDPR proof cookie consent dialog from @grrr/cookie-consent with radio inputs +Screenshot of the GDPR proof cookie consent dialog from @grrr/cookie-consent with checkbox inputs ### Developed with ❤️ by [GRRR](https://grrr.nl) -- GRRR is a [B Corp](https://grrr.nl/en/b-corp/) -- GRRR has a [tech blog](https://grrr.tech/) -- GRRR is [hiring](https://grrr.nl/en/jobs/) -- [@GRRRTech](https://twitter.com/grrrtech) tweets +- GRRR is a [B Corp](https://grrr.nl/en/b-corp/) +- GRRR has a [tech blog](https://grrr.tech/) +- GRRR is [hiring](https://grrr.nl/en/jobs/) +- [@GRRRTech](https://twitter.com/grrrtech) tweets ## Installation @@ -24,38 +23,52 @@ $ npm install @grrr/cookie-consent ``` -Note: depending on your setup [additional configuration might be needed](https://github.com/grrr-amsterdam/cookie-consent/wiki/Usage-with-build-tools). This package is published with untranspiled JavaScript, as EcmaScript Modules (ESM). +## Custom element + +This cookie-consent module is a [custom element](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements). This also means that the element is encapsulated in a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM). Here follows some information of how to implement this custom element in your own project. ## Usage Import the module and register it as a custom element: ```js -import CookieConsent from '@grrr/cookie-consent'; +import CookieConsent from "@grrr/cookie-consent"; -window.customElements.define("cookie-consent", cookieConsent); +if (window.customElements.get("cookie-consent") === undefined) { + window.customElements.define("cookie-consent", cookieConsent); +} ``` -Once registered, you can add the cookie-consent element to your HTML: - -```html - -``` +Once registered, you can add the cookie-consent element to your HTML, you can pass custom data attributes for the: -### Conditional content +- title +- description +- save button text +- cookie types -Conditionally show or hide elements. Add the `data-cookie-consent-`-attribute with the id of the required cookie consent type. There are two types of state: `accepted` and `rejected`. +```js +const cookies = [ + { + id: "functional", // string + label: functionalCookiesLabel, // string + description: functionalCookiesDescription, // string + required: true, // boolean + }, + { + id: "marketing", // string + label: marketingCookiesLabel, // string + description: marketingCookiesDescription, // string + checked: marketingCookiesAccepted, // boolean + }, +]; +// in order to pass these as a data-attribute we'll need to transform them to a string first +const stringifiedCookies = JSON.stringify(cookies); +``` ```html - - +; ``` -Notes: - -- When hiding, the module will add `aria-hidden="true"` and `style="display: none;"` to remove it from the DOM. -- When showing, the module will remove any inline set `display` style, along with any `hidden` or `aria-hidden` attributes. - ## Options To use the options, add them as data attributes to the custom element: @@ -64,17 +77,9 @@ To use the options, add them as data attributes to the custom element: privacy policy.

" // The description of the dialog. + Read more in our privacy policy.

" // The description of the dialog. data-saveButtonText="Save preferences" // The save button label. - data-cookies={[ // Array with cookie types. - { - "id": "marketing", // The unique identifier of the cookie type. - "label": "Marketing", // The label used in the dialog. - "description": "...", // The description used in the dialog. - "required": false, // Mark a cookie required (ignored when type is `radio`). - "checked": true, // The default checked state (only valid when not `required`). - }, - ]} + data-cookies=cookies /> ``` @@ -82,75 +87,42 @@ To use the options, add them as data attributes to the custom element: All options except `cookies` are optional. They will fall back to the defaults, which are listed here: ```js -{ - type: 'checkbox', // Can be `checkbox` or `radio`. - prefix: 'cookie-consent', // The prefix used for styling and identifiers. - append: true, // By default the dialog is appended before the `main` tag or - // as the first `body` child. Disable to append it yourself. - appendDelay: 500, // The delay after which the cookie consent should be appended. - acceptAllButton: false, // Nudge users to accept all cookies when nothing is selected. - // Will select all checkboxes, or the top radio button. - cookies: [ // Array with cookie types. - { - id: 'marketing', // The unique identifier of the cookie type. - label: 'Marketing', // The label used in the dialog. - description: '...', // The description used in the dialog. - required: false, // Mark a cookie required (ignored when type is `radio`). - checked: false, // The default checked state (only valid when not `required`). - }, - ], - // If you need to override the dialog template (default defined in renderDialog) - dialogTemplate: function(templateVars) { - return '...' - }, - // Labels to provide content for the dialog. - labels: { - title: 'Cookies & Privacy', - description: `

This site makes use of third-party cookies. Read more in our - privacy policy.

`, - // Button labels based on state and preferences. - button: { - // The default button label. - default: 'Save preferences', - // Shown when `acceptAllButton` is set, and no option is selected. - acceptAll: 'Accept all', - }, - // ARIA labels to improve accessibility. - aria: { - button: 'Confirm cookie settings', - tabList: 'List with cookie types', - tabToggle: 'Toggle cookie tab', +export const DEFAULTS = { + type: "checkbox", + prefix: "cookie-consent", + append: true, + appendDelay: 500, + acceptAllButton: false, + labels: { + title: "Cookies & Privacy", + description: + '

This site makes use of third-party cookies. Read more in our privacy policy.

', + button: { + default: "Save preferences", + acceptAll: "Accept all", + }, + aria: { + button: "Confirm cookie settings", + tabList: "List with cookie types", + tabToggle: "Toggle cookie tab", + }, }, - }, -} +}; ``` ## API -- [CookieConsent()](#cookieconsentoptions-object) -- [show()](#showdialog) -- [hide()](#hidedialog) -- [isAccepted()](#isacceptedid-string) -- [getPreferences()](#getpreferences) -- [on()](#on) -- [updatePreference()](#updatePreferencecookies-array) - -### CookieConsent(options: object) - -To make use the (for instance to add event listeners elsewhere), add it as a custom element after the instance has been created: - -```js -window.customElements.define("cookie-consent", cookieConsent); -``` +- [show()](#showdialog) +- [hide()](#hidedialog) ### show() Will show the dialog element, for example to show it when triggered to change settings. ```js -el.addEventListener('click', e => { - e.preventDefault(); - cookieConsent.show(); +button.addEventListener("click", (e) => { + e.preventDefault(); + cookieConsent.show(); }); ``` @@ -159,98 +131,9 @@ el.addEventListener('click', e => { Will hide the dialog element. ```js -el.addEventListener('click', e => { - e.preventDefault(); - cookieConsent.hide(); -}); -``` - -### isAccepted(id: string) - -Check if a certain cookie type has been accepted. Will return `true` when accepted, `false` when denied, and `undefined` when no action has been taken. - -```js -const acceptedMarketing = cookieConsent.isAccepted('marketing'); // => true, false, undefined -``` - -### getPreferences() - -Will return an array with preferences per cookie type. - -```js -const preferences = cookieConsent.getPreferences(); - -// [ -// { -// "id": "analytical", -// "accepted": true -// }, -// { -// "id": "marketing", -// "accepted": false -// } -// ] -``` - -### on(event: string) - -Add listeners for events. Will fire when the event is dispatched from the CookieConsent module. -See available [events](#events). - -```js -cookieConsent.on('event', eventHandler); -``` - - -### updatePreference(cookies: array) - -Update cookies programmatically. - -By updating cookies programmatically, the event handler will receive an update method. - -```js -const cookies = [ - { - id: 'marketing', - label: 'Marketing', - description: '...', - required: false, - checked: true, - }, - { - id: 'simple', - label: 'Simple', - description: '...', - required: false, - checked: false, - }, -]; - -cookieConsent.updatePreference(cookies); -``` - -## Events - -Events are bound by the [on](#onevent-string) method. - -- [update](#update) - -### update - -Will fire whenever the cookie settings are updated, or when the instance is constructed and stored preferences are found. It returns the array with cookie preferences, identical to the `getPreferences()` method. - -This event can be used to fire tag triggers for each cookie type, for example via Google Tag Manager (GTM). In the following example trackers are loaded via a trigger added in GTM. Each cookie type has it's own trigger, based on the `cookieType` variable, and the trigger itself is invoked by the `cookieConsent` event. - -Example: - -```js -cookieConsent.on('update', cookies => { - const accepted = cookies.filter(cookie => cookie.accepted); - const dataLayer = window.dataLayer || []; - accepted.forEach(cookie => dataLayer.push({ - event: 'cookieConsent', - cookieType: cookie.id, - })); +el.addEventListener("click", (e) => { + e.preventDefault(); + cookieConsent.hide(); }); ``` @@ -258,82 +141,80 @@ cookieConsent.on('update', cookies => { No styling is being applied by the JavaScript module. However, there is a default stylesheet in the form of a [Sass](https://sass-lang.com/) module which can easily be added and customized to your project and its needs. -You have to use `::parts` pseudo-element to style the dialog and its elements due to the Shadow DOM encapsulation. You can style the dialog and its elements by using the following parts: +You have to use the `::parts` pseudo-element to style the dialog and its elements due to the Shadow DOM encapsulation. You can style the dialog and its elements by using the following parts: ```scss cookie-consent::part(cookie-consent) { - // Styles for the cookie consent dialog + // Styles for the cookie consent dialog } /** * Header */ wookie-consent::part(cookie-consent__header) { - // Styles for the cookie consent header + // Styles for the cookie consent header } cookie-consent::part(cookie-consent__title) { - // Styles for the cookie consent title + // Styles for the cookie consent title } /** * Tabs */ wookie-consent::part(cookie-consent__tab-list) { - // Styles for the cookie consent tab list + // Styles for the cookie consent tab list } wookie-consent::part(cookie-consent__tab-list-item) { // Styles for the cookie consent tab list item } cookie-consent::part(cookie-consent__tab) { - // Styles for the cookie consent tabs + // Styles for the cookie consent tabs } /** * Tab option (label with input in it) & tab toggle */ cookie-consent::part(cookie-consent__option) { - // Styles for the tab option label + // Styles for the tab option label } cookie-consent::part(cookie-consent__input) { - // Styles for the tab option input + // Styles for the tab option input } cookie-consent::part(cookie-consent__tab-toggle) { - // Styles for the tab toggle + // Styles for the tab toggle } cookie-consent::part(cookie-consent__tab-toggle-icon) { - // Styles for the tab toggle icon + // Styles for the tab toggle icon } /** * Tab panel (with description) */ cookie-consent::part(cookie-consent__tab-panel) { - // Styles for the tab panel + // Styles for the tab panel } cookie-consent::part(cookie-consent__tab-description) { - // Styles for the tab description + // Styles for the tab description } /** * Button */ cookie-consent::part(cookie-consent__button) { - // styles for the consent button + // styles for the consent button } cookie-consent::part(cookie-consent__button-text) { - // Styles for the consent button text + // Styles for the consent button text } ``` ### Stylesheet -View the [base stylesheet](https://github.com/grrr-amsterdam/cookie-consent/tree/master/styles/cookie-consent.scss). - -Note: no vendor prefixes are applied. We recommend using something like [Autoprefixer](https://github.com/postcss/autoprefixer) to do that automatically. +View the [base stylesheet](https://github.com/grrr-amsterdam/cookie-consent/tree/master/styles/cookie-consent.scss). ### Interface With the styling from the base module applied, the interface will look roughly like this (fonts, sizes and margins might differ): -Screenshot of the GDPR proof cookie consent dialog from @grrr/cookie-consent +Screenshot of the GDPR proof cookie consent dialog from @grrr/cookie-consent with checkbox inputs