{"_id":"@auroratide/flip-card","name":"@auroratide/flip-card","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@auroratide/flip-card","version":"0.1.0","description":"A card of content with a front and back, beautifully flips.","type":"module","main":"lib/index.js","module":"lib/index.js","keywords":["card","web component","flip"],"author":{"name":"Timothy Foster","url":"https://auroratide.com"},"homepage":"https://auroratide.github.io/web-components/flip-card","repository":{"type":"git","url":"git+https://github.com/Auroratide/web-components.git"},"license":"ISC","devDependencies":{"@open-wc/testing":"^4.0.0","@web/test-runner":"^0.18.0","typescript":"^5.3.3"},"scripts":{"clean":"rm -rf lib","build":"tsc","build:watch":"tsc -w","test":"wtr --node-resolve --port 10007 test","test:clean":"pnpm clean && pnpm build && pnpm test"},"types":"./lib/index.d.ts","bugs":{"url":"https://github.com/Auroratide/web-components/issues"},"_id":"@auroratide/flip-card@0.1.0","_integrity":"sha512-nLfuakpFvh5gZSlxa452+KGNKXPkfDJ5A1KkueVSX8bPZcz8vQdRIVMfE0cbHxj0eAnJZv+5dmXggHNBdyW0jw==","_resolved":"/private/var/folders/bk/zbxm0bcj609gs34tt_wxngfr0000gn/T/58055004c778cf1cecbe60beb947a6c5/auroratide-flip-card-0.1.0.tgz","_from":"file:auroratide-flip-card-0.1.0.tgz","_nodeVersion":"19.4.0","_npmVersion":"9.2.0","dist":{"integrity":"sha512-nLfuakpFvh5gZSlxa452+KGNKXPkfDJ5A1KkueVSX8bPZcz8vQdRIVMfE0cbHxj0eAnJZv+5dmXggHNBdyW0jw==","shasum":"49a96485f98e570ddd08f71abcef1796cb521a3e","tarball":"https://registry.npmjs.org/@auroratide/flip-card/-/flip-card-0.1.0.tgz","fileCount":14,"unpackedSize":25359,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiTLszkcOdo2w+xf07B+bIVom1alsXIlAK60G19T2QaAIgbh60HyNmmwke9WnrSqQfrTPvS5ZjKdk90YOoOd9N34o="}]},"_npmUser":{"name":"auroratide","email":"tf.auroratide@gmail.com"},"directories":{},"maintainers":[{"name":"auroratide","email":"tf.auroratide@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/flip-card_0.1.0_1708115742903_0.4796192985551093"},"_hasShrinkwrap":false}},"time":{"created":"2024-02-16T20:35:42.791Z","0.1.0":"2024-02-16T20:35:43.063Z","modified":"2024-02-16T20:35:43.714Z"},"maintainers":[{"name":"auroratide","email":"tf.auroratide@gmail.com"}],"description":"A card of content with a front and back, beautifully flips.","homepage":"https://auroratide.github.io/web-components/flip-card","keywords":["card","web component","flip"],"repository":{"type":"git","url":"git+https://github.com/Auroratide/web-components.git"},"author":{"name":"Timothy Foster","url":"https://auroratide.com"},"bugs":{"url":"https://github.com/Auroratide/web-components/issues"},"license":"ISC","readme":"# The flip-card Element\n\n<p hidden><strong><a href=\"https://auroratide.github.io/web-components/flip-card\">View this page with live demos!</a></strong></p>\n\nThe `flip-card` element represents content with a front side and a back side, with one side presented at a time.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<flip-card class=\"default\">\n\t\t<section slot=\"front\">\n\t\t\t<p>The front!</p>\n\t\t</section>\n\t\t<section slot=\"back\">\n\t\t\t<p>The back!</p>\n\t\t</section>\n\t</flip-card>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```html\n<flip-card>\n\t<section slot=\"front\">\n\t\t<p>The front!</p>\n\t</section>\n\t<section slot=\"back\">\n\t\t<p>The back!</p>\n\t</section>\n</flip-card>\n```\n\n\n## Installation\n\nYou can import through CDN:\n\n```html\n<script type=\"module\" src=\"https://unpkg.com/@auroratide/flip-card/lib/define.js\"></script>\n```\n\nOr, you may install through [NPM](https://www.npmjs.com/package/@auroratide/flip-card) and include it as part of your build process:\n\n```\n$ npm i @auroratide/flip-card\n```\n\n```javascript\nimport \"@auroratide/flip-card/lib/define.js\"\n```\n\n\n## Usage\n\n`flip-card` is a **markup element** that can be used in your HTML. When you use it, you must specify a **front** slot and a **back** slot, using the `slot` attribute on the direct descendents.\n\n```html\n<flip-card>\n\t<section slot=\"front\">\n\t\t<p>The front!</p>\n\t</section>\n\t<section slot=\"back\">\n\t\t<p>The back!</p>\n\t</section>\n</flip-card>\n```\n\n### Controlling the visible side\n\nBy default, the front of the card is show, and the backside is hidden. Using the `facedown` attribute, you can make the backside show instead.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<flip-card class=\"default\" facedown>\n\t\t<section slot=\"front\">\n\t\t\t<p>The front!</p>\n\t\t</section>\n\t\t<section slot=\"back\">\n\t\t\t<p>The back!</p>\n\t\t</section>\n\t</flip-card>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```html\n<flip-card facedown>\n\t<!-- ... -->\n</flip-card>\n```\n\n### Flipping the card\n\nYou can flip a card with Javascript by either setting its `facedown` property, or by calling the `flip()` method on the element.\n\n```js\nconst card = document.querySelector(\"flip-card\")\n\ncard.facedown = true\n\ncard.flip()\n```\n\n## Customizing the Card\n\nSince it's Just HTML<sup>TM</sup>, you can use good ol' CSS to customize the card, with a few special things you can do.\n\n```css\nflip-card {\n\twidth: 15em;\n\theight: 20em;\n}\n```\n\n### Card Edges\n\nLike in real life, these cards have some thickness! The effect is subtle, but makes a great difference in how the flip feels.\n\n* The `--card-depth` CSS propery lets you customize the card's thickness.\n* The `::part(edge)` CSS selector lets you customize the edge's color and other properties.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<flip-card class=\"coin\">\n\t\t<section slot=\"front\">\n\t\t\t<p>Heads</p>\n\t\t</section>\n\t\t<section slot=\"back\">\n\t\t\t<p>Tails</p>\n\t\t</section>\n\t</flip-card>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```css\nflip-card {\n\t--card-depth: 1em;\n}\n\nflip-card::part(edge) {\n\tbackground-color: oklch(20% 0.066 255);\n}\n```\n\n### Rounded corners\n\n* Use the `border-radius` CSS property to make rounded corners, but it must be a single absolute length.\n* The `--corner-granularity` CSS property is an integer that represents how smooth the 3D curve is on a card's rounded corners. Higher is smoother; default is `4`.\n* Call `recreateBorderRadius()` anytime the card's sizes or border-radius's sizes change.\n\n`border-radius` on the card rounds the corners (mostly) like you would expect. It's a bit of a magic trick to make the card's edge rounded, as curved 3D surfaces don't exist in HTML/CSS. As a result there are some limitations.\n\nThe following won't look very good unless the card's thickness is 0.\n\n* Percentage-based border radius (e.g. `border-radius: 50%`)\n* Different border radii for different corners (e.g. `border-radius: 1em 0.5em`)\n* Elliptical border radius (e.g. `border-radius: 1em / 0.5em`)\n* Dynamically changing the border radius on the fly\n\nAdditionally, because curved 3D surfaces don't exist, the element must _simulate_ a curved surface using lots of small flat surfaces. You can use the `--corner-granularity` CSS property to control how smooth the border-radius looks edge-on. In general, if you have a large border radius, you want a bigger `--corner-granularity`. It is an integer.\n\nFor example, the first coin has low corner granularity, and the second coin has high corner granularity.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<div class=\"card-container\" style=\"--flip-duration: 2s;\">\n\t\t<flip-card class=\"coin\" style=\"--corner-granularity: 3;\">\n\t\t\t<section slot=\"front\">\n\t\t\t\t<p>Front</p>\n\t\t\t</section>\n\t\t\t<section slot=\"back\">\n\t\t\t\t<p>Back</p>\n\t\t\t</section>\n\t\t</flip-card>\n\t\t<flip-card class=\"coin\" style=\"--corner-granularity: 16;\">\n\t\t\t<section slot=\"front\">\n\t\t\t\t<p>Front</p>\n\t\t\t</section>\n\t\t\t<section slot=\"back\">\n\t\t\t\t<p>Back</p>\n\t\t\t</section>\n\t\t</flip-card>\n\t</div>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```css\nflip-card {\n\t--corner-granularity: 16;\n\tborder-radius: 5em;\n}\n```\n\nFinally, there is an escape hatch! If you find yourself dynamically changing the dimensions of the card or its border radius, you can manually call the `recreateBorderRadius()` method to reformat the corners. It's up to you to decide when this is needed, but if you have an unchanging card, then it probably isn't needed at all.\n\n### Flip height and duration\n\nThe following apply to the default animation.\n\n* The `--flip-height` CSS property customizes how high the card lifts off the surface. The default is \n* The `--flip-duration` CSS property customizes how long the flip lasts.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<flip-card class=\"default long-and-high\">\n\t\t<section slot=\"front\">\n\t\t\t<p>Front</p>\n\t\t</section>\n\t\t<section slot=\"back\">\n\t\t\t<p>Back</p>\n\t\t</section>\n\t</flip-card>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```css\nflip-card {\n\t--flip-height: 40em;\n\t--flip-duration: 1.5s;\n}\n```\n\n### 3D perspective\n\nBy default, each card lives in its own 3D context. That's just to make it super easy to get a single `flip-card` working.\n\nHowever, if you have multiple cards, you may find it looks wrong. That's because in reality, we view the world in a single **perspective**: our own perspective.\n\nAs such, to get the most realistic card flips when there are multiple cards, you may want to put them all in the same 3D perspective context. You can do this with two steps:\n\n1. Apply `perspective: none` CSS to every `flip-card` element.\n2. Make all your `flip-card` elements direct children of a container with non-zero `perspective`.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<div class=\"card-container\">\n\t\t<flip-card class=\"default\">\n\t\t\t<section slot=\"front\">\n\t\t\t\t<p>Front</p>\n\t\t\t</section>\n\t\t\t<section slot=\"back\">\n\t\t\t\t<p>Back</p>\n\t\t\t</section>\n\t\t</flip-card>\n\t\t<flip-card class=\"default\">\n\t\t\t<section slot=\"front\">\n\t\t\t\t<p>Front</p>\n\t\t\t</section>\n\t\t\t<section slot=\"back\">\n\t\t\t\t<p>Back</p>\n\t\t\t</section>\n\t\t</flip-card>\n\t\t<flip-card class=\"default\">\n\t\t\t<section slot=\"front\">\n\t\t\t\t<p>Front</p>\n\t\t\t</section>\n\t\t\t<section slot=\"back\">\n\t\t\t\t<p>Back</p>\n\t\t\t</section>\n\t\t</flip-card>\n\t\t<flip-card class=\"default\">\n\t\t\t<section slot=\"front\">\n\t\t\t\t<p>Front</p>\n\t\t\t</section>\n\t\t\t<section slot=\"back\">\n\t\t\t\t<p>Back</p>\n\t\t\t</section>\n\t\t</flip-card>\n\t</div>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```css\n.card-container {\n\tperspective: 125em;\n\tperspective-origin: center;\n}\n\n.card-container flip-card {\n\tperspective: none;\n}\n```\n\n### Fully custom animations\n\nYou can use the `setFlipToFrontAnimation()` and `setFlipToBackAnimation()` methods in Javascript to give the card a different flip animation.\n\nHere's an example for a vertical flip, rather than a horizontal flip.\n\n<!--DEMO\n<wc-demo class=\"flip-card-demo\">\n\t<flip-card class=\"default vertical-flip\">\n\t\t<section slot=\"front\">\n\t\t\t<p>The front!</p>\n\t\t</section>\n\t\t<section slot=\"back\">\n\t\t\t<p>The back!</p>\n\t\t</section>\n\t</flip-card>\n\t<div slot=\"actions\">\n\t\t<button>Flip!</button>\n\t</div>\n</wc-demo>\n/DEMO-->\n\n```js\ncard.setFlipToFrontAnimation(\n\t[ {\n\t\ttransform: \"translateZ(calc(-1 * var(--_depth))) rotateX(180deg)\",\n\t}, {\n\t\ttransform: \"translateZ(var(--_height)) rotateX(270deg)\",\n\t}, {\n\t\ttransform: \"translateZ(0em) rotateX(360deg)\",\n\t} ],\n\t{\n\t\teasing: \"ease-in-out\",\n\t},\n)\n\ncard.setFlipToBackAnimation(\n\t[ {\n\t\ttransform: \"translateZ(0em) rotateX(0deg)\",\n\t}, {\n\t\ttransform: \"translateZ(var(--_height)) rotateX(90deg)\",\n\t}, {\n\t\ttransform: \"translateZ(calc(-1 * var(--_depth))) rotateX(180deg)\",\n\t} ],\n\t{\n\t\teasing: \"ease-in-out\",\n\t},\n)\n```\n\n(and a dash of CSS too, to orient the backside properly at rest)\n\n```css\nflip-card > [slot=\"back\"] {\n\ttransform: scale(-1);\n}\n```\n\n\nThe `flip-card` component uses the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API) to perform animations, rather than CSS. This confers some advantages, such as being able to generate animations on the fly or apply easing to the entire animation rather than just keyframes. It's also necessary in order to penetrate the Shadow DOM properly.\n\nEach method has the same interface as the Element's [animate()](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) method:\n\n* The first parameter is a list of keyframes. The `offset` property is equivalent to defining percentage in CSS's equivalent `@keyframes`. See [Keyframe Formats](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats) for details.\n* The second parameter are options, such as number of iterations or easing. See [KeyframeEffect's object parameter](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#parameters) for details.\n\n### All customization options in a single list\n\n| Name | Default | Description |\n| ------------- | ------------- | ------------- |\n| `--card-depth` | `0.15em` | How thick the card's edge is. |\n| `--flip-height` | `20em` | How high the card travels vertically when flipped. |\n| `--flip-duration` | `0.75s` | How long it takes the card to complete a flip. |\n| `--flip-duration` | `0.75s` | How long it takes the card to complete a flip. |\n| `--corner-granularity` | `4` | How smooth the card's corner edges should be when rounded. Higher is smoother. |\n| `setFlipToFrontAnimation()` | a horizontal flip | Animation to play when flipping the card from being face down to being face up. Parameters are keyframes and options. |\n| `setFlipToBackAnimation()` | a horizontal flip | Animation to play when flipping the card from being face up to being face down. Parameters are keyframes and options. |\n\n## Events\n\nThe `flip-card` element dispatches the following events:\n\n| Name | When Triggered |\n| ------------- | ------------- |\n| `flipping` | Whenever the card begins to flip. |\n| `flipped` | Whenever the card's flip animation ends. |\n\nBoth events contain in their details a property `facedown` indicating to which side the card is flipping or flipped.\n\n```js\ncard.addEventListener('flipping', e => {\n\tconsole.log(e.detail.facedown)\n})\n```\n\n## Accessibility\n\nThis custom element is build with accessibility in mind!\n\n* Screenreaders only announce the side that is visible.\n* Screenreaders announce \"Frontside\" or \"Backside\" to denote which side is visible.\n* Tabbable elements on the non-facing side of the card cannot be focused until the card is flipped.\n* The flip animation is disabled for people who [prefer reduced motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion).\n\n### Labelling Cards\n\nThe `flip-card` element does not prescribe a specific way to accessibly label the card's content, as the best way to do this depends on the card's context. Possibilities include:\n\n* Wrapping the card in an `article` element if its contents are self-contained.\n* Labelling the card with text within the card itself using `aria-labelledby`, with `role=\"region\"`.\n* Simply putting a heading element above the card.\n* Wrapping the card in a `figure` element and using `figcaption` to label it.\n\n### Announcing when the card flips\n\nIf you attach `aria-live=\"polite\"` to the `flip-card`, then flipping the card will announce the new side's contents to screen readers. As this may not always be desired behaviour, it is up to you to discern whether adding `aria-live` will make your content more accessible.\n","readmeFilename":"README.md"}