{"id":4536,"date":"2026-06-18T11:01:53","date_gmt":"2026-06-18T08:01:53","guid":{"rendered":"https:\/\/notes.profidev.online\/?p=4536"},"modified":"2026-06-18T11:32:54","modified_gmt":"2026-06-18T08:32:54","slug":"recipe-card","status":"publish","type":"post","link":"https:\/\/notes.profidev.online\/ru\/reactjs\/4536\/","title":{"rendered":"Recipe Card React.js"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong><strong><a href=\"https:\/\/notes.profidev.online\/cards\/4533\/\" data-type=\"link\" data-id=\"https:\/\/notes.profidev.online\/reactjs\/4517\/\">HTML version<\/a><\/strong><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe title=\"Recipe Card\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/YLamcVL3cHs?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;jsx&quot;,&quot;mime&quot;:&quot;text\/jsx&quot;,&quot;theme&quot;:&quot;cobalt&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:false,&quot;fileName&quot;:&quot;JSX&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;JSX&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;jsx&quot;}\">\/\/App.jsx\n\nimport { useState } from 'react'\nimport '.\/App.css'\n\nconst ingredients = [\n  { text: '12 ounces burrata', defaultChecked: true },\n  { text: '2 cups cherry tomatoes', defaultChecked: false },\n  { text: '1 Tbsp olive oil', defaultChecked: false },\n  { text: '1 Tbsp balsamic vinegar', defaultChecked: false },\n  { text: '2 tsp honey', defaultChecked: false },\n  { text: '1 clove garlic', defaultChecked: false },\n  { text: '\u00bd tsp dried basil', defaultChecked: false },\n  { text: '1 tsp chopped fresh thyme', defaultChecked: false },\n  { text: '\u00bc tsp dried oregano', defaultChecked: false },\n  { text: 'salt &amp; pepper', defaultChecked: false },\n  { text: 'chili flakes', defaultChecked: false },\n  { text: '1 baguette', defaultChecked: false },\n]\n\nconst directions = [\n  'Preheat oven to 375\u00b0F.',\n  'Slice tomatoes and toss in oil, balsamic vinegar, honey, garlic, basil, thyme, and oregano. Season with salt and pepper.',\n  'Slice baguette and drizzle with olive oil.',\n  'Toast up bread in a hot skillet until golden brown.',\n  'Spread on fresh burrata cheese.',\n  'Top with marinated tomato slices. Then bake for 12-15 minutes.',\n  'Top with parmesan, warm marinara sauce, oregano, and chili flakes.',\n]\n\nexport default function App() {\n  const [isOpen, setIsOpen] = useState(false)\n  const [checkedIngredients, setCheckedIngredients] = useState(\n    ingredients.map((ing) =&gt; ing.defaultChecked)\n  )\n  const [checkedDirections, setCheckedDirections] = useState(\n    Array(directions.length).fill(false)\n  )\n\n  const toggleIngredient = (i) =&gt; {\n    setCheckedIngredients((prev) =&gt; prev.map((v, idx) =&gt; (idx === i ? !v : v)))\n  }\n\n  const toggleDirection = (i) =&gt; {\n    setCheckedDirections((prev) =&gt; prev.map((v, idx) =&gt; (idx === i ? !v : v)))\n  }\n\n  return (\n    &lt;div className=&quot;absolute top-0 left-0 w-full z-50 h-screen flex justify-center items-center p-4 md:p-6 lg:p-8&quot;&gt;\n      &lt;div className=&quot;max-w-lg bg-gradient-to-b from-white\/60 to-white\/30 text-[#1c0708] backdrop-blur-[.65em] border-[1px] border-solid border-white border-opacity-10 rounded-2xl shadow-black\/50 overflow-hidden shadow-2xl hover:-translate-y-1 hover:shadow-black\/75 hover:backdrop-blur-[1em] transition&quot;&gt;\n\n        &lt;div className=&quot;grid place-items-center grid-cols-6 gap-2&quot;&gt;\n          &lt;div className=&quot;col-span-3 p-8&quot;&gt;\n            &lt;h2 className=&quot;font-bold text-2xl&quot;&gt;\n              Burrata &amp; Balsamic Roasted Tomato Crostini\n            &lt;\/h2&gt;\n            &lt;div className=&quot;tag-lines&quot;&gt;\n              &lt;span className=&quot;tag&quot;&gt;Dairy&lt;\/span&gt;{' '}\n              &lt;span className=&quot;tag&quot;&gt;Vegetarian&lt;\/span&gt;{' '}\n              &lt;span className=&quot;tag&quot;&gt;Mediterranean&lt;\/span&gt;\n            &lt;\/div&gt;\n            &lt;p className=&quot;text-sm text-[#1c0708]\/60&quot;&gt;\n              Oven-roasted tomatoes &lt;br \/&gt; and herbs paired with smooth burrata cheese, served on baked bread.\n            &lt;\/p&gt;\n            &lt;div className={`panel-heading${isOpen ? ' active' : ''}`} role=&quot;tab&quot;&gt;\n              &lt;h4 className=&quot;panel-title&quot;&gt;\n                &lt;a\n                  href=&quot;#&quot;\n                  onClick={(e) =&gt; { e.preventDefault(); setIsOpen(!isOpen) }}\n                  className={`mt-6 py-3 px-5 inline-flex bg-[#e84118] hover:bg-[#c23616] transition-colors text-gray-200 font-bold rounded-full text-sm${isOpen ? '' : ' collapsed'}`}\n                  role=&quot;button&quot;\n                &gt;\n                  See Recipe\n                &lt;\/a&gt;\n              &lt;\/h4&gt;\n            &lt;\/div&gt;\n          &lt;\/div&gt;\n          &lt;div className=&quot;col-span-3 -mt-5 -mb-10&quot;&gt;\n            &lt;img alt=&quot;&quot; className=&quot;recipe_img&quot; src=&quot;https:\/\/assets.codepen.io\/4927073\/tomato_board2.png&quot; \/&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n\n        &lt;div className={`panel-collapse${isOpen ? ' open' : ''}`}&gt;\n          &lt;div className=&quot;panel-body&quot;&gt;\n            &lt;div className=&quot;panel-top&quot;&gt;\n              &lt;div className=&quot;level-item&quot;&gt;\n                &lt;div&gt;\n                  &lt;div className=&quot;heading&quot;&gt;Total Servings: 2&lt;\/div&gt;\n                  &lt;div className=&quot;heading&quot;&gt;Prep Time: 5 min&lt;\/div&gt;\n                &lt;\/div&gt;\n              &lt;\/div&gt;\n            &lt;\/div&gt;\n\n            &lt;div className=&quot;ingredients&quot;&gt;\n              &lt;h3 className=&quot;ingredients&quot;&gt;Ingredients:&lt;\/h3&gt;\n              &lt;ul className=&quot;ingredients&quot;&gt;\n                {ingredients.map((ing, i) =&gt; (\n                  &lt;li key={i}&gt;\n                    &lt;label&gt;\n                      &lt;input\n                        type=&quot;checkbox&quot;\n                        checked={checkedIngredients[i]}\n                        onChange={() =&gt; toggleIngredient(i)}\n                      \/&gt;{' '}\n                      &lt;span&gt;{ing.text}&lt;\/span&gt;\n                    &lt;\/label&gt;\n                  &lt;\/li&gt;\n                ))}\n              &lt;\/ul&gt;\n            &lt;\/div&gt;\n\n            &lt;div className=&quot;directions&quot;&gt;\n              &lt;h3 className=&quot;directions&quot;&gt;Directions:&lt;\/h3&gt;\n              &lt;ol className=&quot;directions&quot;&gt;\n                {directions.map((step, i) =&gt; (\n                  &lt;li key={i}&gt;\n                    &lt;label&gt;\n                      &lt;input\n                        type=&quot;checkbox&quot;\n                        checked={checkedDirections[i]}\n                        onChange={() =&gt; toggleDirection(i)}\n                      \/&gt;{' '}\n                      &lt;span&gt;{step}&lt;\/span&gt;\n                    &lt;\/label&gt;\n                  &lt;\/li&gt;\n                ))}\n              &lt;\/ol&gt;\n            &lt;\/div&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  )\n}\n<\/pre><\/div>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;css&quot;,&quot;mime&quot;:&quot;text\/css&quot;,&quot;theme&quot;:&quot;cobalt&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:false,&quot;fileName&quot;:&quot;CSS&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;CSS&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;css&quot;}\">#root {\n  width: 100%;\n  height: 100%;\n}\n\nbody {\n  background: url(https:\/\/assets.codepen.io\/4927073\/AdobeStock_78589840.jpeg)\n    center\/cover no-repeat fixed;\n  font: 1em\/1.618 Inter, sans-serif;\n}\n\nh2 {\n  font-family: 'Playfair Display', serif;\n  font-size: 36px !important;\n  font-weight: 100 !important;\n  padding: 0 0 5px 0;\n  width: 160%;\n  text-shadow: -0.5px -0.5px 0.5px rgb(0 0 0 \/ 30%),\n    1px 1px 2px rgb(212 212 212 \/ 30%);\n  mix-blend-mode: hard-light;\n}\n\n.tag-lines {\n  position: relative;\n  margin: 5px 0 7px 2px;\n  gap: 5px;\n  width: 120%;\n}\n\nspan.tag {\n  align-items: center;\n  background-color: hsl(0deg 0% 96% \/ 85%);\n  border-radius: 5px;\n  color: #4a4a4a;\n  display: inline-flex;\n  font-size: 11px;\n  height: 20px;\n  justify-content: center;\n  line-height: 1.5;\n  padding-left: 6px;\n  padding-right: 6px;\n  white-space: nowrap;\n  font-family: 'Roboto Condensed', sans-serif;\n  margin-right: 2px;\n  text-shadow: 0.5px 0.5px 0.5px rgb(255 255 255 \/ 50%);\n}\n\np.text-sm {\n  filter: drop-shadow(0.25px 0.25px 0.25px rgb(25 25 25 \/ 65%)) contrast(4.25)\n    saturate(3.5) opacity(0.65);\n  text-shadow: 0.5px 0.5px 0.5px hsl(0deg 0% 95% \/ 35%),\n    -0.25px -0.25px 0.25px hsl(0deg 0% 50% \/ 15%) !important;\n  font-weight: 300;\n  color: rgb(28 7 8 \/ 0.6);\n  font-size: 16px;\n  font-family: Roboto;\n  mix-blend-mode: darken;\n  letter-spacing: 0.125px;\n  width: 125%;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 11px;\n  text-transform: uppercase;\n  letter-spacing: 1px;\n  font-family: &quot;Roboto&quot;, sans-serif;\n  color: white;\n}\n\n.panel-title &gt; a,\n.panel-title &gt; a:active {\n  z-index: 5;\n  position: relative;\n  display: block;\n  text-decoration: none;\n  color: #fdfdfd;\n  border: 1px solid rgba(0, 0, 0, 0.25);\n  box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.35);\n}\n\n.panel-heading a:before {\n  font-family: &quot;Ionicons&quot;;\n  content: &quot;\\f123&quot;;\n  float: right;\n  transition: all 0.5s;\n}\n\n.panel-title a:before {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n\n.panel-title a.collapsed:before {\n  -webkit-transform: rotate(0);\n  -moz-transform: rotate(0);\n  transform: rotate(0);\n}\n\n.panel-collapse {\n  overflow: hidden;\n  max-height: 0;\n  transition: max-height 0.4s ease;\n}\n\n.panel-collapse.open {\n  max-height: 900px;\n}\n\n.panel-body {\n  padding: 20px 30px 30px 30px;\n  position: relative;\n  background-color: hsl(0deg 0% 98% \/ 75%);\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  box-shadow: 0px 0.5vh 5px 0px rgba(0, 0, 0, 0.25);\n}\n\nul.ingredients {\n  display: grid;\n  grid-template-columns: 2fr 2fr 2fr;\n  font-size: 13px;\n  width: 100%;\n  padding: 0 !important;\n  margin: auto;\n  gap: 0px 5px;\n  top: -10px;\n  position: relative;\n  line-height: 1.5;\n  text-wrap: nowrap;\n  text-overflow: ellipsis;\n  grid-template-rows: repeat(5, 2fr);\n  grid-auto-flow: column;\n}\n\nli:nth-child(4),\nli:nth-child(8) {\n  grid-column: span 1;\n  grid-row: span 2;\n  text-wrap: wrap;\n}\n\nul.ingredients li {\n  &amp;:hover {\n    color: #3298dc;\n  }\n}\n\nul.ingredients li input {\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  &amp;::before {\n    color: #666;\n    font-family: &quot;Font Awesome 5 Free&quot;;\n    font-weight: 900;\n    content: &quot;\\f0c8&quot;;\n    margin-right: 0.25rem;\n  }\n  &amp;:checked {\n    ~ span {\n      font-style: italic;\n      color: #666;\n      text-decoration: line-through;\n    }\n    &amp;::before {\n      content: &quot;\\f14a&quot;;\n    }\n  }\n}\n\n.panel-body h3.ingredients {\n  width: 100%;\n  margin: auto;\n  padding: 0 0 4px 2px;\n  top: -12px;\n  position: relative;\n  font-family: 'Inter', sans-serif;\n  font-weight: 500;\n  letter-spacing: 0.4px;\n  font-size: 17px;\n}\n\n.panel-top {\n  width: 100%;\n  padding: 0;\n  top: -10px;\n  position: relative;\n  margin-bottom: -28px;\n  right: -15px;\n  text-align: justify;\n}\n\n.level-item {\n  right: 0;\n  position: relative;\n  display: flex;\n  justify-content: flex-end;\n  text-align: right;\n}\n\n.heading {\n  display: block;\n  font-size: 10px;\n  letter-spacing: 1px;\n  margin-bottom: 2px;\n  text-transform: uppercase;\n  line-height: 1.35;\n}\n\n.directions {\n  width: 100%;\n}\n\n.panel-body h3.directions {\n  width: 100%;\n  margin: auto;\n  padding: 0 0 0px 2px;\n  position: relative;\n  font-family: 'Inter', sans-serif;\n  font-weight: 500;\n  letter-spacing: 0.4px;\n  font-size: 17px;\n  top: -2px;\n}\n\nol.directions {\n  list-style: auto;\n  list-style-position: outside;\n  margin-left: 32px;\n  font-size: 13px;\n  line-height: 1.45;\n}\n\nol li {\n  counter-increment: cupcake;\n}\n\nol li::marker {\n  content: none;\n}\n\nol li::before {\n  content: counter(cupcake);\n  width: 13px;\n  height: 13px;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  line-height: 1;\n  margin-left: -23px;\n  position: relative;\n  left: -5.5px;\n  top: -2px;\n  z-index: 1;\n  font-size: 10px;\n  font-weight: 500;\n  font-family: Roboto;\n  color: #30363d;\n  text-shadow: 0.5px 0.5px 0.5px rgb(255 255 255 \/ 75%);\n}\n\nol.directions li input {\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  &amp;::before {\n    content: &quot;&quot;;\n    margin-right: 0.25rem;\n    box-shadow: #0004 0 1px 2px 0, #0003 0 0.5px 2px 1px,\n      1px 1px 10px 2px #00000026;\n    background-color: #fff;\n    background-image: linear-gradient(\n      180deg,\n      #ffffff 10%,\n      hsl(216, 4%, 85%) 60%,\n      80%,\n      hsl(216, 4%, 70%)\n    );\n    z-index: 0 !important;\n    width: 13px;\n    height: 13px;\n    display: inline-flex;\n    margin-left: -16px;\n    position: relative;\n    left: -3px;\n    top: 1px;\n    border-radius: 50%;\n  }\n  &amp;:checked {\n    ~ span {\n      font-style: italic;\n      color: #666;\n      text-decoration: line-through;\n    }\n    &amp;::before {\n      content: &quot;&quot;;\n      box-shadow: hsl(0, 0%, 65%) 0 1px 1px 1px, 0 -1px 2px 1px #fff;\n      background: linear-gradient(\n        0deg,\n        hsl(0, 0%, 90%) 5%,\n        hsl(0, 0%, 95%) 15%,\n        hsl(0, 0%, 100%) 40%,\n        hsl(0, 0%, 95%) 55%,\n        hsl(0, 0%, 70%) 90%\n      );\n      outline: none;\n    }\n  }\n}\n\nimg.recipe_img {\n  content: url(https:\/\/assets.codepen.io\/4927073\/tomato_board2.png);\n  object-fit: cover;\n  width: 350px !important;\n  height: auto;\n  position: relative;\n  max-width: fit-content;\n  z-index: -1;\n  transform: rotate(6deg);\n  top: 2px;\n  right: 18px;\n  filter: drop-shadow(4.5px 4.5px 6px var(--dcolor)) saturate(1.3) opacity(0.95)\n    contrast(0.9) brightness(0.95);\n  --dcolor: #332315;\n}\n\n<\/pre><\/div>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;markdown&quot;,&quot;mime&quot;:&quot;text\/x-markdown&quot;,&quot;theme&quot;:&quot;cobalt&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:false,&quot;fileName&quot;:&quot;Markdown&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Markdown&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;markdown&quot;}\"># Recipe Card \u2014 Burrata &amp; Balsamic Roasted Tomato Crostini\n\nGlassmorphic recipe card with accordion expand and interactive checkboxes.\n\n## Files\n\n- `App.jsx` \u2014 component\n- `App.css` \u2014 styles\n\n## Setup\n\n1. Copy `App.jsx` and `App.css` into your project\n2. Add to `index.html` before `&lt;\/head&gt;`:\n\n```html\n&lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.4.2\/css\/all.min.css&quot;&gt;\n&lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/code.ionicframework.com\/ionicons\/2.0.1\/css\/ionicons.min.css&quot;&gt;\n&lt;script src=&quot;https:\/\/cdn.tailwindcss.com&quot;&gt;&lt;\/script&gt;\n```\n\n3. Requires React 18 + Vite 5\n\n## Notes\n\n- Fonts (Playfair Display, Inter, Roboto, Roboto Condensed) are loaded from the system \u2014 no separate import needed\n- Accordion is powered by `useState` + CSS `max-height` transition (no Bootstrap)\n- Checkboxes are controlled inputs; icons use Font Awesome 6 solid set (`font-weight: 900`)\n- Page background is set on `body`; requires `#root { width: 100%; height: 100%; }` to fill the viewport\n\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>HTML version<\/p>","protected":false},"author":1,"featured_media":4553,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[141,66],"tags":[],"class_list":["post-4536","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cards_reactjs","category-reactjs"],"_links":{"self":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts\/4536","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/comments?post=4536"}],"version-history":[{"count":3,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts\/4536\/revisions"}],"predecessor-version":[{"id":4542,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts\/4536\/revisions\/4542"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/media\/4553"}],"wp:attachment":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/media?parent=4536"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/categories?post=4536"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/tags?post=4536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}