{"id":15518750,"url":"https://github.com/ines/quickstart","last_synced_at":"2025-04-23T04:15:05.712Z","repository":{"id":98232268,"uuid":"91591414","full_name":"ines/quickstart","owner":"ines","description":"🎯 A micro-form for user-specific installation instructions","archived":false,"fork":false,"pushed_at":"2017-05-18T17:21:56.000Z","size":25,"stargazers_count":67,"open_issues_count":0,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-23T04:14:59.473Z","etag":null,"topics":["css","docs","documentation","javascript","javascript-library"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ines.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-17T15:22:41.000Z","updated_at":"2024-01-04T16:14:07.000Z","dependencies_parsed_at":"2023-05-18T19:45:23.005Z","dependency_job_id":null,"html_url":"https://github.com/ines/quickstart","commit_stats":{"total_commits":9,"total_committers":2,"mean_commits":4.5,"dds":"0.11111111111111116","last_synced_commit":"7db8bb0b329313a26fe05c3538f68c60ff3dfd33"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fquickstart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fquickstart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fquickstart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fquickstart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ines","download_url":"https://codeload.github.com/ines/quickstart/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250366716,"owners_count":21418772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["css","docs","documentation","javascript","javascript-library"],"created_at":"2024-10-02T10:19:14.429Z","updated_at":"2025-04-23T04:15:05.694Z","avatar_url":"https://github.com/ines.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# quickstart.js: A micro-form for user-specific installation instructions\n\nIf you're publishing open-source software, you're probably familiar with this\nscenario: You want to make it easy for your users to download, install and\nuse your library across operating systems and platforms, so you upload it to\na variety of package managers and provide detailed instructions and documentation.\n\nBut each package manager has its own, specific download command – sometimes even\ntwo. If you want to use a virtual environment, you need to add a few commands to\nthe top. But wait, the activation command in Windows looks different. And if\nyou're on Python 3, it's actually called `venv`, not `virtualenv`. And after\ninstallation, there's other stuff to set up and install. How? Well...\n\n![It depends...](https://cloud.githubusercontent.com/assets/13643239/26151827/c2de05d6-3b04-11e7-8ea0-67087b177d10.gif)\n\nThe problem with linear installations docs is that they easily become verbose.\nYou want to make sure to cover every platform and setup, while at the same\ntime, keeping it simple for beginners or users who just want to install your\nsoftware, and not sift through lengthy explanations that are not actually\nrelevant to them. This ended up becoming an annoying issue for us at\n[spaCy](https://spacy.io), so I built [`quickstart.js`](quickstart.js). It's\n[super lightweight](https://raw.githubusercontent.com/ines/quickstart/master/quickstart.min.js), easy to customise and will even build\nthe form for you – if you want it to.\n\n**Quickstart was inspired by [PyTorch](http://pytorch.org)'s \"Getting started\"\nwidget. Its filtering functionality is based on a simple CSS rule, similar\nto [Jets.js](https://jets.js.org). This makes it fast and allows complex\nfiltering rules with only one minimal DOM modification.** For more info on\nthis, see the [How it works](#how-it-works) section.\n\n## Examples\n\nYou can see Quickstart in action on [spaCy's installation docs](https://spacy.io/docs/usage).\nFor a code example you can modify, see the [`example.html`](example.html) or\ncheck out [this demo on CodePen](https://codepen.io/ines/pen/OmobKq).\n\n![Screenshot](https://cloud.githubusercontent.com/assets/13643239/26161117/4891b0e2-3b23-11e7-9a9d-965dd50f58e9.jpg)\n\n\u003e ⚠️ **Important note:**  Because Quickstart relies on JavaScript, I strongly\n\u003e recommend to only use it **in addition to existing installation docs**, not\n\u003e to provide new information that's not available elsewhere. Otherwise, users\n\u003e who don't have JavaScript enabled won't be able to access your docs.\n\u003e Quickstart will make sure its container is visible, so you can safely set it\n\u003e to `display: none` in your CSS or HTML. This will hide it if JavaScript is\n\u003e disabled.\n\n## Usage\n\nQuickstart can take care of rendering the widget and the markup required for the\nform and options – all you have to do is **include the script and stylesheet**:\n\n```html\n\u003c!-- in \u003chead\u003e --\u003e\n\u003clink rel=\"stylesheet\" href=\"quickstart.css\"\u003e\n\n\u003c!--- before \u003c/body\u003e --\u003e\n\u003cscript src=\"quickstart.min.js\"\u003e\u003c/script\u003e\n```\n\nOptions are defined as a **simple array**. Each group and  option needs to have a\nunique `id` and a `title`, which will be displayed in the form. To allow multiple\nselections in a group, set `multiple: true`. To mark an option as checked by\ndefault, add `checked: true`.\n\n```javascript\nconst groups = [\n    {\n        id: \"os\",\n        title: \"Operating system\",\n        options: [\n            { id: \"mac\", title: \"macOS / OSX\", checked: true },\n            { id: \"windows\", title: \"Windows\" },\n            { id: \"linux\", title: \"Linux\" }\n        ]\n    },\n    {\n        id: \"python\",\n        title: \"Python version\",\n        options: [\n            { id: 2, title: \"2.x\" },\n            { id: 3, title: \"3.x\", checked: true }\n        ]\n    },\n    {\n        id: \"config\",\n        title: \"Configuration\",\n        multiple: true,\n        options: [\n            { id: \"venv\", title: \"virtualenv\" }\n        ]\n    }\n]\n```\n\nYou also need to set up a container to tell Quickstart **where to put the widget**,\nwhich **commands or instructions** are available and when to display them. This\nis all done in **plain HTML**, to make it easy to update and edit.\n\nEach command is a simple `\u003cspan\u003e` with data attributes `data-qs-` plus the ID\nof the option group. For example, a command with `data-qs-os=\"windows\"` will\nonly be shown if the user has selected `windows` from the group `os`. If a\ncommand has more than one condition specified, it will only be shown if\n**all conditions are true**. Note that Quickstart currently does not support\nadding multiple values per group. If a command is the same for both `mac` and\n`linux`, for example, you'll have to add it twice.\n\n```html\n\u003cdiv id=\"quickstart\"\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-python=\"2\"\u003epython -m pip install -U virtualenv\u003c/span\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-python=\"3\"\u003epython -m pip install -U venv\u003c/span\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-python=\"2\"\u003evirtualenv .env\u003c/span\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-python=\"3\"\u003evenv .env\u003c/span\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-os=\"mac\"\u003esource .env/bin/activate\u003c/span\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-os=\"linux\"\u003esource .env/bin/activate\u003c/span\u003e\n    \u003cspan data-qs-config=\"venv\" data-qs-os=\"windows\"\u003e.env\\Scripts\\activate\u003c/span\u003e\n\u003c/div\u003e\n```\n\nYou can now **initialise the widget** with the selector of the container (in\nthis case, `#quickstart` for `\u003cdiv id=\"quickstart\"\u003e`) and the array of option\ngroups:\n\n```javascript\nconst qs = new Quickstart('#quickstart', groups)\n```\n\nOptionally, `Quickstart` can take a third argument, an object containing custom\nsettings. The following settings are available:\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| `noInit` | boolean | `false` | Don't initialise the widget on load. This means you can call or add an event listener using `Quickstart.init()` yourself whenever and however you want. |\n| `prefix` | string | `'qs'` | Prefix to use for data attributes and class names, i.e. `data-[prefix]-` and `.[prefix]-`.  |\n\n## How it works\n\nQuickstart uses a technique similar to the one powering\n[Jets.js](https://jets.js.org/), a native CSS search engine (see their website\nfor more info, including a pretty cool animation and speed comparison). Instead\nof filtering the elements in Javascript and modifying them one by one, only a\nsingle CSS expression is added. Here's the gist:\n\nLet's say you have a condition, like `os == \"mac\"` and you want to show or hide\nDOM elements based on whether or not they match. (You also want to do this in\nVanilla JS without a Virtual DOM and other helpers, so removing and re-adding\nelements is out of the question and too expensive.) First, you need to label the\nelements you want to show or hide, for example by assigning them a class like\n`.os-mac`, or in this case, a data attribute   `data-qs-os=\"mac\"`.\n\nEvery time an input value changes, you need to update the\nDOM to reflect that change. For exampe, you could iterate over all elements,\ncheck if they have `data-qs-os` set to `\"mac\"` and if not, hide them – either\nby adding a class `.hide`, or setting them to `display: none`. You also need to\nun-hide previously hidden elements if they now *do match*.  Now if your elements\ncontain more than one condition, for example, `os == mac \u0026\u0026 python == 2`, you\ncan't get away with only filtering the elements based on the user's\nlatest decision – you also need to take all previous settings into account.\nYou'll only know whether the element matches the condition by checking the\nsettings for both `os` **and** `python`. This becomes easier with query selectors\nlike `:checked`, but it's still **a lot of computation on\neach click.**\n\nInstead, Quickstart only writes one CSS rule on each update, for example:\n\n```css\n[data-qs-results] \u003e [data-qs-os]:not([data-qs-os=\"mac\"]) { display: none }\n```\n\nThis means: All elements that are direct children of the results wrapper, have a\n`data-qs-os` attribute, i.e. depend on the operating system, but do not have\n`data-qs-os` set to `\"mac\"`, will be hidden. This ensures that only elements\nthat match **all conditions** are visible.\n\nIf multiple selections are allowed, all checked options for that group are\nfetched, for example `[data-qs-model]:checked`, and combined into one expression:\n\n```css\n[data-qs-results] \u003e [data-qs-model]:not([data-qs-model=\"en\"]):not([data-qs-model=\"de\"]) { display: none }\n```\n\n\u003e ⁉️ **Why not compile one large expression for all possible cases upfront?** In\n\u003e theory, the sibling selector `~` would let you hide elements that are siblings\n\u003e of a `:checked` input – e.g. `[name=\"os\"][value=\"mac\"]:checked ~\n\u003e [data-qs-os]:not([data-qs-os=\"mac\"]) { display: none }`. So you *could* generate\n\u003e a giant expression like this based on the available groups and options, and\n\u003e scrap the event listeners and other JavaScript logic. But this only works for\n\u003e **siblings**, meaning that the inputs, labels and commands would all have to\n\u003e live in the same container. This is inconvenient and very limiting, both in\n\u003e terms of semantics and styling options.\n\n## Using Quickstart with your own markup\n\nWhile Quickstart is able to generate the form markup and all required wrappers,\nyou **don't have to** do it that way and are free to use your own custom markup\ninstead. This is especially useful if you want to apply your own classes and\nstyling, or add more info to the form.\n\nWhen you initialise Quickstart **without a `groups` argument**, it will look\nfor groups in your HTML markup – specifically, elements with the `data-qs-group`\nattribute. It will then add the required style tags and event listeners to them.\nQuickstart will also check if theres a `data-qs-results` attribute present\nin your markup. If so, it won't create it for you.\n\nHere's an example of a very basic widget:\n\n```html\n\u003cdiv id=\"quickstart\" class=\"qs\"\u003e\n    \u003cfieldset class=\"qs-group\" data-qs-group=\"os\"\u003e\n        \u003clegend class=\"qs-legend\"\u003eOperating system\u003c/legend\u003e\n        \u003cinput class=\"qs-input qs-input--radio\" type=\"radio\" name=\"os\" id=\"mac\" value=\"mac\" checked\u003e\n        \u003clabel class=\"qs-label\" for=\"mac\"\u003emacOS / OSX\u003c/label\u003e\n\n        \u003cinput class=\"qs-input qs-input--radio\" type=\"radio\" name=\"os\" id=\"windows\" value=\"windows\"\u003e\n        \u003clabel class=\"qs-label\" for=\"windows\"\u003eWindows\u003c/label\u003e\n\n        \u003cinput class=\"qs-input qs-input--radio\" type=\"radio\" name=\"os\" id=\"linux\" value=\"linux\"\u003e\n        \u003clabel class=\"qs-label\" for=\"linux\"\u003eLinux\u003c/label\u003e\n    \u003c/fieldset\u003e\n    \u003cfieldset class=\"qs-group\" data-qs-group=\"config\"\u003e\n        \u003clegend class=\"qs-legend\"\u003eConfiguration\u003c/legend\u003e\n        \u003cinput class=\"qs-input qs-input--checkbox\" type=\"checkbox\" name=\"config\" id=\"venv\" value=\"venv\"\u003e\n        \u003clabel class=\"qs-label\" for=\"venv\"\u003evirtualenv\u003c/label\u003e\n    \u003c/fieldset\u003e\n\n    \u003cpre class=\"qs-code\"\u003e\n        \u003ccode class=\"qs-results\" data-qs-results\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-python=\"2\"\u003epython -m pip install -U virtualenv\u003c/span\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-python=\"3\"\u003epython -m pip install -U venv\u003c/span\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-python=\"2\"\u003evirtualenv .env\u003c/span\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-python=\"3\"\u003evenv .env\u003c/span\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-os=\"mac\"\u003esource .env/bin/activate\u003c/span\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-os=\"linux\"\u003esource .env/bin/activate\u003c/span\u003e\n            \u003cspan data-qs-config=\"venv\" data-qs-os=\"windows\"\u003e.env\\Scripts\\activate\u003c/span\u003e\n        \u003c/code\u003e\n    \u003c/pre\u003e\n\u003c/div\u003e\n```\n\nIf you're using your own markup Quickstart won't mess with it and simply trust\nyou to know what you're doing. The only thing it'll add is a `\u003cstyle\u003e` tag\nfor each group, containing its filtering logic. It also won't add any CSS classes\nor remove anything else within its container. **Quickstart's only reference points\nto the DOM are the  `data-qs-group` and `data-qs-results` attributes.**\n\n## Styling Quickstart\n\nQuickstart comes with a very basic and minimal [stylesheet](quickstart.css).\nUnder the hood, multi-select options are rendered as `\u003cinput type=\"checkbox\"\u003e`,\nand single-select options as `\u003cinput type=\"radio\"\u003e`. By default, they're hidden,\nwith custom styles applied to the `\u003clabel\u003e` **following a checked input** and\nits `:before` pseudo-element. This creates the illusion of styled radio buttons\nand checkboxes. If you're letting Quickstart generate the markup for you, it'll\ncome with the following classes:\n\n| Name | Description |\n| --- | --- |\n| `.qs` | Container of quickstart widget. |\n| `.qs-group` | A single option group. |\n| `.qs-legend` | Title of a single option group. |\n| `.qs-input` | Input field. |\n| `.qs-input--radio` | Input field of `type=\"radio\"`. |\n| `.qs-input--checkbox` | Input field of `type=\"checkbox\"`. |\n| `.qs-label` | Input label. |\n| `.qs-code` | Code block containing the results. |\n| `.qs-results` | Results, i.e. available commands for a configuration. |\n\nIf you have a custom `prefix` set in your options, `qs` will be replaced with\nthat.\n\n\n\u003e ⚠️ **Important note:** When styling option groups, keep in mind that the\n\u003e default markup generated by Quickstart will render them as `\u003cfieldset\u003e`\n\u003e elements with `\u003clegend\u003e` titles – the recommended and semantically correct\n\u003e way for groups of form fields. However, those elements can sometimes behave\n\u003e in unexpected ways, especially across browsers, and don't always follow the\n\u003e same logic as `\u003cdiv\u003e` or `\u003cspan\u003e` elements (for more information, see\n\u003e [this blog post](https://thatemil.com/blog/2015/01/03/reset-your-fieldset/)\n\u003e on resetting fieldsets).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fines%2Fquickstart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fines%2Fquickstart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fines%2Fquickstart/lists"}