|
1 |
| -import { component$, Slot, useSignal, useVisibleTask$ } from '@builder.io/qwik'; |
| 1 | +import { |
| 2 | + component$, |
| 3 | + QwikIntrinsicElements, |
| 4 | + Slot, |
| 5 | + useSignal, |
| 6 | + useVisibleTask$, |
| 7 | +} from '@builder.io/qwik'; |
2 | 8 | import {
|
3 | 9 | Combobox,
|
4 | 10 | ComboboxControl,
|
@@ -1107,60 +1113,205 @@ export const HighlightedExample = component$(() => {
|
1107 | 1113 |
|
1108 | 1114 | // // Using context example.
|
1109 | 1115 |
|
1110 |
| -// import { createContextId, useContext, useContextProvider } from '@builder.io/qwik'; |
| 1116 | +import { createContextId, useContext, useContextProvider } from '@builder.io/qwik'; |
| 1117 | +import { StatusBadge } from '../../../_components/component-status-badge/component-status-badge'; |
| 1118 | +import { statusByComponent } from 'apps/website/src/_state/component-statuses'; |
1111 | 1119 |
|
1112 |
| -// // Create a context ID |
1113 |
| -// export const AnimalContext = createContextId<string[]>('animal-context'); |
| 1120 | +// Create a context ID |
| 1121 | +export const AnimalContext = createContextId<string[]>('animal-context'); |
1114 | 1122 |
|
1115 |
| -// export const ContextExample = component$(() => { |
1116 |
| -// const animals = ['Armadillo', 'Donkey', 'Baboon', 'Badger', 'Barracuda', 'Bat', 'Bear']; |
1117 |
| -// // Provide the animals array to the context under the context ID |
1118 |
| -// useContextProvider(AnimalContext, animals); |
| 1123 | +export const ContextExample = component$(() => { |
| 1124 | + const animals = ['Armadillo', 'Donkey', 'Baboon', 'Badger', 'Barracuda', 'Bat', 'Bear']; |
| 1125 | + // Provide the animals array to the context under the context ID |
| 1126 | + useContextProvider(AnimalContext, animals); |
1119 | 1127 |
|
1120 |
| -// return <ContextChild />; |
1121 |
| -// }); |
| 1128 | + return <ContextChild />; |
| 1129 | +}); |
1122 | 1130 |
|
1123 |
| -// export const ContextChild = component$(() => { |
1124 |
| -// const animals = useContext(AnimalContext); |
| 1131 | +export const ContextChild = component$(() => { |
| 1132 | + const animals = useContext(AnimalContext); |
1125 | 1133 |
|
1126 |
| -// return ( |
1127 |
| -// <PreviewCodeExample> |
1128 |
| -// <div class="flex flex-col gap-4" q:slot="actualComponent"> |
1129 |
| -// <Combobox options={animals} class="relative"> |
1130 |
| -// <ComboboxLabel class=" font-semibold text-white">Animals 🐖</ComboboxLabel> |
1131 |
| -// <ComboboxControl class="bg-[#1f2532] flex items-center rounded-sm border-slate-400 border-[1px] relative"> |
1132 |
| -// <ComboboxInput class="px-2 w-44 bg-slate-900 px-d2 pr-6 text-white placeholder:text-slate-500" /> |
1133 |
| -// <ComboboxTrigger class="w-6 h-6 group absolute right-0"> |
1134 |
| -// <ComboboxIcon class="stroke-white group-aria-expanded:-rotate-180 transition-transform duration-[450ms]" /> |
1135 |
| -// </ComboboxTrigger> |
1136 |
| -// </ComboboxControl> |
1137 |
| -// <ComboboxPortal> |
1138 |
| -// <ComboboxListbox |
1139 |
| -// flip={true} |
1140 |
| -// gutter={8} |
1141 |
| -// class="w-44 bg-slate-900 px-4 py-2 rounded-sm border-slate-400 border-[1px]" |
1142 |
| -// optionRenderer$={(option: ResolvedOption, index: number) => ( |
1143 |
| -// <ComboboxOption |
1144 |
| -// index={index} |
1145 |
| -// resolved={option} |
1146 |
| -// class="aria-disabled:text-slate-600 aria-disabled:hover:bg-slate-700 rounded-sm px-2 hover:bg-slate-500 aria-selected:bg-slate-500 text-white border-2 border-transparent aria-selected:border-slate-200 group" |
1147 |
| -// > |
1148 |
| -// <span class="block group-aria-selected:translate-x-[3px] transition-transform duration-350"> |
1149 |
| -// <span>{option.label}</span> |
1150 |
| -// </span> |
1151 |
| -// </ComboboxOption> |
1152 |
| -// )} |
1153 |
| -// /> |
1154 |
| -// </ComboboxPortal> |
1155 |
| -// </Combobox> |
1156 |
| -// </div> |
| 1134 | + return ( |
| 1135 | + <PreviewCodeExample> |
| 1136 | + <div class="flex flex-col gap-4" q:slot="actualComponent"> |
| 1137 | + <Combobox options={animals} class="relative"> |
| 1138 | + <ComboboxLabel class=" font-semibold text-white">Animals 🐖</ComboboxLabel> |
| 1139 | + <ComboboxControl class="bg-[#1f2532] flex items-center rounded-sm border-slate-400 border-[1px] relative"> |
| 1140 | + <ComboboxInput class="px-2 w-44 bg-slate-900 px-d2 pr-6 text-white placeholder:text-slate-500" /> |
| 1141 | + <ComboboxTrigger class="w-6 h-6 group absolute right-0"> |
| 1142 | + <ComboboxIcon class="stroke-white group-aria-expanded:-rotate-180 transition-transform duration-[450ms]" /> |
| 1143 | + </ComboboxTrigger> |
| 1144 | + </ComboboxControl> |
| 1145 | + <ComboboxPortal> |
| 1146 | + <ComboboxListbox |
| 1147 | + flip={true} |
| 1148 | + gutter={8} |
| 1149 | + class="w-44 bg-slate-900 px-4 py-2 rounded-sm border-slate-400 border-[1px]" |
| 1150 | + optionRenderer$={(option: ResolvedOption, index: number) => ( |
| 1151 | + <ComboboxOption |
| 1152 | + index={index} |
| 1153 | + resolved={option} |
| 1154 | + class="aria-disabled:text-slate-600 aria-disabled:hover:bg-slate-700 rounded-sm px-2 hover:bg-slate-500 aria-selected:bg-slate-500 text-white border-2 border-transparent aria-selected:border-slate-200 group" |
| 1155 | + > |
| 1156 | + <span class="block group-aria-selected:translate-x-[3px] transition-transform duration-350"> |
| 1157 | + <span>{option.label}</span> |
| 1158 | + </span> |
| 1159 | + </ComboboxOption> |
| 1160 | + )} |
| 1161 | + /> |
| 1162 | + </ComboboxPortal> |
| 1163 | + </Combobox> |
| 1164 | + </div> |
1157 | 1165 |
|
1158 |
| -// <div q:slot="codeExample"> |
1159 |
| -// <Slot /> |
1160 |
| -// </div> |
1161 |
| -// </PreviewCodeExample> |
1162 |
| -// ); |
1163 |
| -// }); |
| 1166 | + <div q:slot="codeExample"> |
| 1167 | + <Slot /> |
| 1168 | + </div> |
| 1169 | + </PreviewCodeExample> |
| 1170 | + ); |
| 1171 | +}); |
| 1172 | + |
| 1173 | +export const SearchBar = component$(() => { |
| 1174 | + const inputValueSig = useSignal(''); |
| 1175 | + const highlightedIndexSig = useSignal(0); |
| 1176 | + const inputRef = useSignal<HTMLInputElement>(); |
| 1177 | + const isListboxOpenSig = useSignal(false); |
| 1178 | + |
| 1179 | + type MyComponents = { |
| 1180 | + component: string; |
| 1181 | + label: string; |
| 1182 | + }; |
| 1183 | + |
| 1184 | + const docsPrefix = '/docs/headless'; |
| 1185 | + const components = [ |
| 1186 | + { component: 'accordion', label: 'Accordion' }, |
| 1187 | + { component: 'combobox', label: 'Combobox' }, |
| 1188 | + { component: 'popover', label: 'Popover' }, |
| 1189 | + { component: 'select', label: 'Select' }, |
| 1190 | + { component: 'separator', label: 'Separator' }, |
| 1191 | + { component: 'tabs', label: 'Tabs' }, |
| 1192 | + { component: 'toggle', label: 'Toggle' }, |
| 1193 | + { component: 'tooltip', label: 'Tooltip' }, |
| 1194 | + ]; |
| 1195 | + |
| 1196 | + return ( |
| 1197 | + <PreviewCodeExample> |
| 1198 | + <div class="flex flex-col items-center gap-4 p-4" q:slot="actualComponent"> |
| 1199 | + <div> |
| 1200 | + <Combobox |
| 1201 | + bind:inputValueSig={inputValueSig} |
| 1202 | + bind:inputRef={inputRef} |
| 1203 | + bind:highlightedIndexSig={highlightedIndexSig} |
| 1204 | + bind:isListboxOpenSig={isListboxOpenSig} |
| 1205 | + optionValueKey="component" |
| 1206 | + class="w-fit" |
| 1207 | + options={components} |
| 1208 | + > |
| 1209 | + <ComboboxLabel class="text-white">Qwik UI ⚡</ComboboxLabel> |
| 1210 | + <ComboboxControl class="bg-[#1f2532] rounded-sm border-slate-400 border-[1px] relative"> |
| 1211 | + <ComboboxInput |
| 1212 | + onClick$={() => (isListboxOpenSig.value = !isListboxOpenSig.value)} |
| 1213 | + class="pl-6 w-44 bg-slate-900 px-d2 pr-6 text-white placeholder:text-slate-500" |
| 1214 | + onKeyDown$={(e) => { |
| 1215 | + if (e.key === 'Enter') { |
| 1216 | + const inputElement = e.target as HTMLInputElement; |
| 1217 | + window.location.href = `${docsPrefix}/${inputElement.value.toLowerCase()}`; |
| 1218 | + } |
| 1219 | + }} |
| 1220 | + /> |
| 1221 | + <ComboboxTrigger class="w-6 h-6 group absolute left-[4px]"> |
| 1222 | + <SearchIcon /> |
| 1223 | + </ComboboxTrigger> |
| 1224 | + {inputValueSig.value.length > 0 && ( |
| 1225 | + // give separate id if two triggers |
| 1226 | + <button |
| 1227 | + id="close-button" |
| 1228 | + aria-label="clear search" |
| 1229 | + onMouseDown$={() => { |
| 1230 | + inputValueSig.value = ''; |
| 1231 | + inputRef.value?.focus(); |
| 1232 | + }} |
| 1233 | + class="w-6 h-6 flex justify-center items-center absolute top-0 right-0" |
| 1234 | + > |
| 1235 | + <ClearIcon class="w-4 h-4" /> |
| 1236 | + </button> |
| 1237 | + )} |
| 1238 | + </ComboboxControl> |
| 1239 | + <ComboboxPortal> |
| 1240 | + <ComboboxListbox |
| 1241 | + gutter={8} |
| 1242 | + class="w-44 bg-slate-900 px-1 py-2 rounded-sm border-slate-400 border-[1px]" |
| 1243 | + hide="escaped" |
| 1244 | + optionRenderer$={(option: ResolvedOption, index: number) => { |
| 1245 | + const searchOption = option.option as MyComponents; |
| 1246 | + return ( |
| 1247 | + <a |
| 1248 | + href={`${docsPrefix}/${searchOption.component}`} |
| 1249 | + aria-label={option.label} |
| 1250 | + > |
| 1251 | + <ComboboxOption |
| 1252 | + key={option.key} |
| 1253 | + class="aria-disabled:text-slate-600 aria-disabled:hover:bg-slate-700 rounded-sm px-2 hover:bg-slate-500 aria-selected:bg-slate-500 text-white border-2 border-transparent aria-selected:border-slate-200 group flex justify-between items-start gap-4" |
| 1254 | + index={index} |
| 1255 | + resolved={option} |
| 1256 | + > |
| 1257 | + <span>{searchOption.label}</span> |
| 1258 | + <span class="scale-[0.9]"> |
| 1259 | + <StatusBadge |
| 1260 | + status={statusByComponent.headless[option.label]} |
| 1261 | + /> |
| 1262 | + </span> |
| 1263 | + </ComboboxOption> |
| 1264 | + </a> |
| 1265 | + ); |
| 1266 | + }} |
| 1267 | + /> |
| 1268 | + </ComboboxPortal> |
| 1269 | + </Combobox> |
| 1270 | + </div> |
| 1271 | + </div> |
| 1272 | + |
| 1273 | + <div q:slot="codeExample"> |
| 1274 | + <Slot /> |
| 1275 | + </div> |
| 1276 | + </PreviewCodeExample> |
| 1277 | + ); |
| 1278 | +}); |
| 1279 | + |
| 1280 | +export function SearchIcon(props: QwikIntrinsicElements['svg'], key: string) { |
| 1281 | + return ( |
| 1282 | + <svg |
| 1283 | + xmlns="http://www.w3.org/2000/svg" |
| 1284 | + width="1em" |
| 1285 | + height="1em" |
| 1286 | + viewBox="0 0 256 256" |
| 1287 | + {...props} |
| 1288 | + key={key} |
| 1289 | + > |
| 1290 | + <path |
| 1291 | + fill="white" |
| 1292 | + d="m228.24 219.76l-51.38-51.38a86.15 86.15 0 1 0-8.48 8.48l51.38 51.38a6 6 0 0 0 8.48-8.48ZM38 112a74 74 0 1 1 74 74a74.09 74.09 0 0 1-74-74Z" |
| 1293 | + ></path> |
| 1294 | + </svg> |
| 1295 | + ); |
| 1296 | +} |
| 1297 | + |
| 1298 | +export function ClearIcon(props: QwikIntrinsicElements['svg'], key: string) { |
| 1299 | + return ( |
| 1300 | + <svg |
| 1301 | + xmlns="http://www.w3.org/2000/svg" |
| 1302 | + width="1em" |
| 1303 | + height="1em" |
| 1304 | + viewBox="0 0 256 256" |
| 1305 | + {...props} |
| 1306 | + key={key} |
| 1307 | + > |
| 1308 | + <path |
| 1309 | + fill="white" |
| 1310 | + d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm37.66 130.34a8 8 0 0 1-11.32 11.32L128 139.31l-26.34 26.35a8 8 0 0 1-11.32-11.32L116.69 128l-26.35-26.34a8 8 0 0 1 11.32-11.32L128 116.69l26.34-26.35a8 8 0 0 1 11.32 11.32L139.31 128Z" |
| 1311 | + ></path> |
| 1312 | + </svg> |
| 1313 | + ); |
| 1314 | +} |
1164 | 1315 |
|
1165 | 1316 | export const AutoPlacementExample = component$(() => {
|
1166 | 1317 | const isListboxOpenSig = useSignal(true);
|
|
0 commit comments