{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"search","title":"Search","description":"Command search with live filtering and an empty state.","dependencies":[],"registryDependencies":["https://ward.so/r/foundation.json","https://ward.so/r/glide-menu.json"],"files":[{"path":"registry/ward/SearchList.tsx","content":"\"use client\";\n/*\n * MIT License\n *\n * Copyright (c) 2026 Shane Levine\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport \"./styles/foundation.css\";\n\nimport { useState } from \"react\";\nimport GlideMenu from \"./GlideMenu\";\n\n/* ─────────────────────────────────────────────────────────\n * SEARCH — command search with live filtering.\n * The field, clear action, and results are directly usable.\n * ───────────────────────────────────────────────────────── */\n\nexport type SearchItem = string;\n\nexport type SearchListLabels = {\n  placeholder: string;\n  ariaLabel: string;\n  emptyTitle: string;\n  emptyHint: string;\n};\n\nconst ITEMS: SearchItem[] = [\n  \"Forecast summer demand\",\n  \"Find design asset suppliers\",\n  \"Compare seasonal projects\",\n  \"Draft project launch plan\",\n  \"Check cold-chain status\",\n  \"Audit sugar costs\",\n  \"Retire low sellers\",\n];\n\nconst LABELS: SearchListLabels = {\n  placeholder: \"Search projects…\",\n  ariaLabel: \"Search projects\",\n  emptyTitle: \"No results found\",\n  emptyHint: \"Adjust your search to try again\",\n};\n\nexport default function SearchList({\n  items = ITEMS,\n  labels = LABELS,\n}: {\n  items?: SearchItem[];\n  labels?: SearchListLabels;\n  variant?: string;\n} = {}) {\n  const [query, setQuery] = useState(\"\");\n  const results = query\n    ? items.filter((i) => i.toLowerCase().includes(query.toLowerCase()))\n    : items.slice(0, 5);\n  const empty = query.length > 2 && results.length === 0;\n\n  return (\n    <div className=\"flex min-h-[248px] w-full max-w-72 flex-col items-stretch\">\n      <div className=\"w-full self-start overflow-hidden rounded-card bg-card shadow-raised\">\n        {/* input row */}\n        <div className=\"flex h-10 items-center gap-2 border-b border-line px-3 transition-colors duration-100 hover:bg-hover\">\n          <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"var(--ink-3)\" strokeWidth=\"2\" strokeLinecap=\"round\" className=\"shrink-0\">\n            <circle cx=\"11\" cy=\"11\" r=\"7\" />\n            <path d=\"M21 21l-4.3-4.3\" />\n          </svg>\n          <input\n            value={query}\n            onChange={(event) => setQuery(event.target.value)}\n            placeholder={labels.placeholder}\n            aria-label={labels.ariaLabel}\n            className=\"min-w-0 flex-1 bg-transparent text-[13px] text-ink outline-none placeholder:text-ink-3\"\n          />\n          {query && (\n            <button\n              aria-label=\"Clear search\"\n              type=\"button\"\n              onClick={() => setQuery(\"\")}\n              className=\"flex size-6 items-center justify-center rounded-full text-ink-3\n                transition-colors duration-100 hover:bg-line/70 hover:text-ink\"\n              style={{ animation: \"fade-in 150ms ease-out both\" }}\n            >\n              <svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\">\n                <path d=\"M18 6L6 18M6 6l12 12\" />\n              </svg>\n            </button>\n          )}\n        </div>\n\n        {/* results / empty state */}\n        {empty ? (\n          <div className=\"flex flex-col items-center justify-center gap-1 px-4 py-8\" style={{ animation: \"fade-in 250ms ease-out both\" }}>\n            <span className=\"mb-1.5 flex size-8 items-center justify-center rounded-control bg-inset text-ink-3 shadow-hairline\">\n              <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\">\n                <circle cx=\"11\" cy=\"11\" r=\"7\" />\n                <path d=\"M21 21l-4.3-4.3\" />\n              </svg>\n            </span>\n            <span className=\"text-[13px] font-medium text-ink\">{labels.emptyTitle}</span>\n            <span className=\"text-[12px] text-ink-3\">{labels.emptyHint}</span>\n          </div>\n        ) : (\n          <div className=\"p-1\">\n            <GlideMenu className=\"flex flex-col gap-px\" highlightClassName=\"inset-x-0 rounded-[6px] bg-hover\">\n              {results.map((item) => (\n                <button\n                  key={item}\n                  data-menu-row\n                  type=\"button\"\n                  onClick={() => setQuery(item)}\n                  className=\"relative z-10 flex h-8 w-full items-center rounded-[6px] px-2 text-left text-[13px] text-ink\"\n                  style={{ animation: \"fade-in 200ms ease-out both\" }}\n                >\n                  {item}\n                </button>\n              ))}\n            </GlideMenu>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n","type":"registry:component","target":"components/ward/SearchList.tsx"}],"meta":{"variants":["Default"],"version":"1.1.0","source":"https://github.com/slev12397/beautiful-ui/blob/44a274e598395ab61e7c96c26fda2758780253b7/components/primitives/SearchList.tsx","access":"free"},"categories":["ui"],"type":"registry:component"}