@nysds/playground 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +25 -0
- package/README.md +364 -0
- package/bin/cli.mjs +223 -0
- package/bin/cli.test.mjs +36 -0
- package/decks/customizing-components.json +97 -0
- package/dist/assets/index-LO1tomgR.css +6 -0
- package/dist/assets/index-bBtGCGL_.js +5190 -0
- package/dist/assets/internal/typescript.js +193739 -0
- package/dist/assets/nys-icon.library-Bi_7DKlD-YSs5zqZy-DXISxj9N.js +609 -0
- package/dist/assets/nys-icon.library-CwuPZJAc-TryaOS7Z.js +600 -0
- package/dist/assets/playground-typescript-worker-BcTrPYfY.js +87 -0
- package/dist/assets/playground-typescript-worker.js +87 -0
- package/dist/favicon.svg +10 -0
- package/dist/index.html +769 -0
- package/dist/nysds-logo.svg +21 -0
- package/dist/nysds-symbol.svg +7 -0
- package/index.html +768 -0
- package/package.json +59 -0
- package/presets/00-welcome.json +8 -0
- package/presets/01-button.json +7 -0
- package/presets/02-alert.json +7 -0
- package/presets/03-badge-and-avatar.json +7 -0
- package/presets/04-text-input.json +7 -0
- package/presets/05-select-radio-checkbox.json +7 -0
- package/presets/06-form-validation.json +7 -0
- package/presets/07-card.json +7 -0
- package/presets/08-accordion.json +7 -0
- package/presets/09-tabs.json +7 -0
- package/presets/10-modal.json +7 -0
- package/presets/11-stepper.json +7 -0
- package/presets/12-table-and-pagination.json +7 -0
- package/presets/13-tooltip-and-dropdown.json +7 -0
- package/presets/14-navigation.json +7 -0
- package/presets/15-page-structure.json +7 -0
- package/presets/16-themes.json +7 -0
- package/presets/17-utility-classes.json +7 -0
- package/presets/README.md +118 -0
- package/public/favicon.svg +10 -0
- package/public/nysds-logo.svg +21 -0
- package/public/nysds-symbol.svg +7 -0
- package/src/app.css +1087 -0
- package/src/debounce.ts +86 -0
- package/src/deck-model.ts +299 -0
- package/src/deck-store.ts +144 -0
- package/src/decks.test.ts +288 -0
- package/src/editor-panes.ts +190 -0
- package/src/editors.ts +92 -0
- package/src/home.ts +225 -0
- package/src/icon-names.ts +117 -0
- package/src/icons.test.ts +58 -0
- package/src/keys.ts +162 -0
- package/src/main.ts +1456 -0
- package/src/playground.config.ts +74 -0
- package/src/playground.ts +261 -0
- package/src/present.ts +398 -0
- package/src/preset-schema.ts +228 -0
- package/src/route.test.ts +56 -0
- package/src/routing.ts +60 -0
- package/src/settings.ts +211 -0
- package/src/starters.ts +86 -0
- package/src/state.test.ts +544 -0
- package/src/state.ts +237 -0
- package/src/theme.ts +82 -0
- package/src/version-catalog.ts +42 -0
- package/src/versions.ts +88 -0
- package/src/wrapper.ts +84 -0
- package/tsconfig.json +25 -0
- package/vite.config.ts +62 -0
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nysds/playground",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A browser playground for the New York State Design System.",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "node bin/cli.mjs",
|
|
7
|
+
"present": "node bin/cli.mjs --present",
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"build": "tsc --noEmit && vite build",
|
|
10
|
+
"preview": "vite preview",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"test": "node --test src/*.test.ts bin/*.test.mjs",
|
|
13
|
+
"prepublishOnly": "npm test && npm run build"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/ITS-HCD/nysds-playground.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://its-hcd.github.io/nysds-playground/",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/ITS-HCD/nysds-playground/issues"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@nysds/components": "1.21.0",
|
|
27
|
+
"@nysds/styles": "1.21.0",
|
|
28
|
+
"idb-keyval": "6.2.2",
|
|
29
|
+
"lz-string": "1.5.0",
|
|
30
|
+
"playground-elements": "0.21.2",
|
|
31
|
+
"vite": "^6.4.3"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^22.20.3",
|
|
35
|
+
"typescript": "^5.9.3"
|
|
36
|
+
},
|
|
37
|
+
"bin": {
|
|
38
|
+
"nysds-playground": "bin/cli.mjs"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"bin",
|
|
42
|
+
"dist",
|
|
43
|
+
"!dist/fonts",
|
|
44
|
+
"public",
|
|
45
|
+
"!public/fonts",
|
|
46
|
+
"src",
|
|
47
|
+
"presets",
|
|
48
|
+
"decks",
|
|
49
|
+
"index.html",
|
|
50
|
+
"vite.config.ts",
|
|
51
|
+
"tsconfig.json"
|
|
52
|
+
],
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=20"
|
|
55
|
+
},
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Welcome",
|
|
3
|
+
"description": "A tour of the three editor tabs, the version menu, and the share link.",
|
|
4
|
+
"html": "<h1>Welcome to the NYSDS Playground</h1>\n\n<p class=\"intro\">\n Edit the <strong>HTML</strong>, <strong>CSS</strong>, and <strong>JS</strong> tabs on the left.\n The preview reloads as you type. Choose <strong>Share</strong> in the toolbar to copy a link that\n carries your code, so anyone who opens it sees exactly what you see.\n</p>\n\n<nys-alert\n type=\"info\"\n heading=\"Pick a version\"\n text=\"The version menu switches which release of the design system the preview loads, so you can compare behavior across releases.\"\n></nys-alert>\n\n<div class=\"actions\">\n <nys-button label=\"Save draft\" variant=\"filled\"></nys-button>\n <nys-button label=\"Cancel\" variant=\"outline\"></nys-button>\n</div>\n",
|
|
5
|
+
"css": ".intro {\n max-width: 60ch;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin-block-start: 1.5rem;\n}\n",
|
|
6
|
+
"js": "// Every NYSDS component fires its own events. Listen for them here.\ndocument.querySelectorAll('nys-button').forEach((button) => {\n button.addEventListener('nys-click', () => {\n console.log('You chose:', button.getAttribute('label'));\n });\n});\n",
|
|
7
|
+
"version": "latest"
|
|
8
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Button",
|
|
3
|
+
"description": "Compare button variants, sizes, and states, including an icon-only button.",
|
|
4
|
+
"html": "<div class=\"nys-display-flex nys-flex-wrap nys-flex-gap-200 nys-margin-b-300\">\n <nys-button id=\"log-button\" label=\"Filled\" variant=\"filled\"></nys-button>\n <nys-button label=\"Outline\" variant=\"outline\"></nys-button>\n <nys-button label=\"Ghost\" variant=\"ghost\"></nys-button>\n <nys-button label=\"Text\" variant=\"text\"></nys-button>\n</div>\n\n<div class=\"nys-display-flex nys-flex-align-center nys-flex-gap-200 nys-margin-b-300\">\n <nys-button label=\"Small\" size=\"sm\"></nys-button>\n <nys-button label=\"Medium\" size=\"md\"></nys-button>\n <nys-button label=\"Large\" size=\"lg\"></nys-button>\n <nys-button circle icon=\"close\" label=\"Close dialog\"></nys-button>\n <nys-button label=\"Disabled\" disabled></nys-button>\n</div>\n\n<p id=\"log\">Click the filled button to see the log update here.</p>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const logButton = document.getElementById('log-button');\nconst log = document.getElementById('log');\nlet clickCount = 0;\n\nlogButton.addEventListener('nys-click', () => {\n clickCount += 1;\n log.textContent = `Filled button clicked ${clickCount} time${clickCount === 1 ? '' : 's'}.`;\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Alert",
|
|
3
|
+
"description": "See every alert type, plus a dismissible alert that spawns a new one.",
|
|
4
|
+
"html": "<div class=\"nys-display-flex nys-flex-column nys-flex-gap-200 nys-margin-b-300\">\n <nys-alert type=\"info\" heading=\"Info alert type\"></nys-alert>\n <nys-alert type=\"success\" heading=\"Success alert type\"></nys-alert>\n <nys-alert type=\"warning\" heading=\"Warning alert type\"></nys-alert>\n <nys-alert type=\"danger\" heading=\"Danger alert type\"></nys-alert>\n <nys-alert type=\"emergency\" heading=\"Emergency alert type\"></nys-alert>\n</div>\n\n<nys-alert\n id=\"dismiss-alert\"\n type=\"info\"\n heading=\"You can dismiss this alert\"\n text=\"Close it with the X in the corner. A new alert appears after you do.\"\n dismissible\n></nys-alert>\n\n<div id=\"alert-host\"></div>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const dismissAlert = document.getElementById('dismiss-alert');\nconst host = document.getElementById('alert-host');\n\ndismissAlert.addEventListener('nys-close', () => {\n const newAlert = document.createElement('nys-alert');\n newAlert.setAttribute('type', 'success');\n newAlert.setAttribute('heading', 'You dismissed the alert');\n newAlert.setAttribute('text', 'This new alert replaced it.');\n newAlert.classList.add('nys-margin-t-300');\n host.appendChild(newAlert);\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Badge and avatar",
|
|
3
|
+
"description": "Badges across every intent and size, plus avatars with an image, initials, and an icon.",
|
|
4
|
+
"html": "<div class=\"nys-display-flex nys-flex-wrap nys-flex-align-center nys-flex-gap-200 nys-margin-b-300\">\n <nys-badge label=\"Base\" prefixIcon></nys-badge>\n <nys-badge label=\"Info\" intent=\"info\" prefixIcon></nys-badge>\n <nys-badge label=\"Success\" intent=\"success\" prefixIcon></nys-badge>\n <nys-badge label=\"Warning\" intent=\"warning\" prefixIcon></nys-badge>\n <nys-badge label=\"Danger\" intent=\"danger\" prefixIcon></nys-badge>\n <nys-badge label=\"Emergency\" intent=\"emergency\" prefixIcon></nys-badge>\n <nys-badge label=\"Small\" size=\"sm\"></nys-badge>\n</div>\n\n<div class=\"nys-display-flex nys-flex-align-center nys-flex-gap-300\">\n <nys-avatar\n image=\"https://placehold.co/64x64\"\n ariaLabel=\"Jane Smith\"\n ></nys-avatar>\n <nys-avatar initials=\"JS\" ariaLabel=\"Jane Smith\"></nys-avatar>\n <nys-avatar icon=\"account_circle\" ariaLabel=\"Guest account\"></nys-avatar>\n</div>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Text input",
|
|
3
|
+
"description": "Text inputs with a description, a required field, an error state, a masked phone number, and a textarea.",
|
|
4
|
+
"html": "<nys-textinput\n id=\"name-field\"\n label=\"Full name\"\n description=\"Enter your name as it appears on your ID.\"\n placeholder=\"Jane Smith\"\n class=\"nys-margin-b-300\"\n></nys-textinput>\n\n<nys-textinput\n id=\"email-field\"\n label=\"Email address\"\n type=\"email\"\n required\n showError\n errorMessage=\"Enter a valid email address.\"\n class=\"nys-margin-b-300\"\n></nys-textinput>\n\n<nys-textinput\n id=\"phone-field\"\n type=\"tel\"\n label=\"Phone number\"\n description=\"The tel type applies an automatic mask.\"\n class=\"nys-margin-b-300\"\n></nys-textinput>\n\n<nys-textarea\n id=\"comments-field\"\n label=\"Comments\"\n description=\"Share any additional details.\"\n class=\"nys-margin-b-300\"\n></nys-textarea>\n\n<nys-button id=\"read-values\" label=\"Read values\"></nys-button>\n<p id=\"log\"></p>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const readButton = document.getElementById('read-values');\nconst log = document.getElementById('log');\n\nreadButton.addEventListener('nys-click', () => {\n const name = document.getElementById('name-field').value;\n const email = document.getElementById('email-field').value;\n const phone = document.getElementById('phone-field').value;\n const comments = document.getElementById('comments-field').value;\n log.textContent = `Name: ${name || '(empty)'} | Email: ${email || '(empty)'} | Phone: ${phone || '(empty)'} | Comments: ${comments || '(empty)'}`;\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Select, radio, checkbox, and toggle",
|
|
3
|
+
"description": "Common choice controls: a select, a radio group, a checkbox group, and a toggle.",
|
|
4
|
+
"html": "<nys-select\n id=\"borough-select\"\n label=\"Select your favorite borough\"\n class=\"nys-margin-b-300\"\n>\n <option value=\"bronx\" label=\"The Bronx\"></option>\n <option value=\"brooklyn\" label=\"Brooklyn\"></option>\n <option value=\"manhattan\" label=\"Manhattan\"></option>\n <option value=\"queens\" label=\"Queens\"></option>\n <option value=\"staten_island\" label=\"Staten Island\"></option>\n</nys-select>\n\n<nys-radiogroup id=\"borough-radiogroup\" label=\"Select your primary residence\" class=\"nys-margin-b-300\">\n <nys-radiobutton name=\"residence\" value=\"bronx\" label=\"The Bronx\"></nys-radiobutton>\n <nys-radiobutton name=\"residence\" value=\"brooklyn\" label=\"Brooklyn\"></nys-radiobutton>\n <nys-radiobutton name=\"residence\" value=\"manhattan\" label=\"Manhattan\"></nys-radiobutton>\n</nys-radiogroup>\n\n<nys-checkboxgroup id=\"landmarks-checkboxgroup\" label=\"Select landmarks you have visited\" class=\"nys-margin-b-300\">\n <nys-checkbox name=\"landmarks\" value=\"adirondacks\" label=\"Adirondacks\"></nys-checkbox>\n <nys-checkbox name=\"landmarks\" value=\"niagara\" label=\"Niagara Falls\"></nys-checkbox>\n <nys-checkbox name=\"landmarks\" value=\"empire-state\" label=\"Empire State Building\"></nys-checkbox>\n</nys-checkboxgroup>\n\n<nys-toggle id=\"notifications-toggle\" label=\"Enable notifications\" name=\"notifications\" value=\"enabled\" class=\"nys-margin-b-300\"></nys-toggle>\n\n<p id=\"log\">Change a control to see its value here.</p>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const log = document.getElementById('log');\n\ndocument.getElementById('borough-select').addEventListener('nys-change', (e) => {\n log.textContent = `Select changed: ${e.detail.value}`;\n});\n\ndocument.getElementById('borough-radiogroup').addEventListener('nys-change', (e) => {\n log.textContent = `Radio group changed: ${e.detail?.value ?? ''}`;\n});\n\ndocument.getElementById('landmarks-checkboxgroup').addEventListener('nys-change', () => {\n const checked = Array.from(document.querySelectorAll('nys-checkbox'))\n .filter((checkbox) => checkbox.checked)\n .map((checkbox) => checkbox.value);\n log.textContent = `Checkboxes changed: ${checked.join(', ') || '(none selected)'}`;\n});\n\ndocument.getElementById('notifications-toggle').addEventListener('nys-change', (e) => {\n log.textContent = `Toggle changed: ${e.detail.checked ? 'on' : 'off'}`;\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Form validation",
|
|
3
|
+
"description": "A small form that validates on submit and shows a success alert.",
|
|
4
|
+
"html": "<form id=\"contact-form\" novalidate>\n <nys-alert id=\"error-summary\" type=\"danger\" heading=\"Please correct the following errors\" class=\"nys-margin-b-300\" hidden>\n <ul id=\"error-list\"></ul>\n </nys-alert>\n\n <nys-alert id=\"success-alert\" type=\"success\" heading=\"Form submitted\" text=\"Thanks, we received your request.\" class=\"nys-margin-b-300\" hidden></nys-alert>\n\n <nys-textinput\n id=\"name-field\"\n label=\"Full name\"\n required\n class=\"nys-margin-b-300\"\n ></nys-textinput>\n\n <nys-select\n id=\"state-field\"\n label=\"State\"\n required\n class=\"nys-margin-b-300\"\n >\n <option value=\"ny\" label=\"New York\"></option>\n <option value=\"nj\" label=\"New Jersey\"></option>\n <option value=\"ct\" label=\"Connecticut\"></option>\n </nys-select>\n\n <nys-checkbox\n id=\"terms-field\"\n label=\"I agree to the terms of service\"\n name=\"terms\"\n required\n class=\"nys-margin-b-300\"\n ></nys-checkbox>\n\n <nys-button type=\"submit\" label=\"Submit\"></nys-button>\n</form>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const form = document.getElementById('contact-form');\nconst errorSummary = document.getElementById('error-summary');\nconst errorList = document.getElementById('error-list');\nconst successAlert = document.getElementById('success-alert');\n\nform.addEventListener('submit', (e) => {\n e.preventDefault();\n\n const errors = [];\n const nameField = document.getElementById('name-field');\n const stateField = document.getElementById('state-field');\n const termsField = document.getElementById('terms-field');\n\n if (!nameField.value) {\n nameField.showError = true;\n nameField.errorMessage = 'Full name is required.';\n errors.push({ id: 'name-field', message: 'Full name is required.' });\n } else {\n nameField.showError = false;\n }\n\n if (!stateField.value) {\n stateField.showError = true;\n stateField.errorMessage = 'Select a state.';\n errors.push({ id: 'state-field', message: 'Select a state.' });\n } else {\n stateField.showError = false;\n }\n\n if (!termsField.checked) {\n termsField.showError = true;\n termsField.errorMessage = 'You must agree to the terms.';\n errors.push({ id: 'terms-field', message: 'You must agree to the terms.' });\n } else {\n termsField.showError = false;\n }\n\n if (errors.length > 0) {\n errorList.innerHTML = errors\n .map((err) => `<li><a href=\"#${err.id}\">${err.message}</a></li>`)\n .join('');\n errorSummary.hidden = false;\n successAlert.hidden = true;\n errorSummary.scrollIntoView({ behavior: 'smooth' });\n } else {\n errorSummary.hidden = true;\n successAlert.hidden = false;\n }\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Card",
|
|
3
|
+
"description": "Three cards laid out in a responsive grid, each with a media image and a footer action.",
|
|
4
|
+
"html": "<div class=\"nys-grid-row nys-grid-gap-300\">\n <div class=\"nys-grid-col-12 nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-4 nys-display-flex\">\n <nys-card\n heading=\"Adirondack Park\"\n description=\"Six million acres of public and private land, the largest park in the contiguous United States.\"\n >\n <img slot=\"media\" src=\"https://placehold.co/400x225\" alt=\"Adirondack Park mountains\" />\n <nys-button slot=\"footer\" label=\"Plan a visit\" fullWidth></nys-button>\n </nys-card>\n </div>\n <div class=\"nys-grid-col-12 nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-4 nys-display-flex\">\n <nys-card\n heading=\"Niagara Falls State Park\"\n description=\"The oldest state park in the United States, established in 1885.\"\n >\n <img slot=\"media\" src=\"https://placehold.co/400x225\" alt=\"Niagara Falls\" />\n <nys-button slot=\"footer\" label=\"Plan a visit\" fullWidth></nys-button>\n </nys-card>\n </div>\n <div class=\"nys-grid-col-12 nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-4 nys-display-flex\">\n <nys-card\n heading=\"Jones Beach State Park\"\n description=\"A barrier island beach on the south shore of Long Island.\"\n >\n <img slot=\"media\" src=\"https://placehold.co/400x225\" alt=\"Jones Beach shoreline\" />\n <nys-button slot=\"footer\" label=\"Plan a visit\" fullWidth></nys-button>\n </nys-card>\n </div>\n</div>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Accordion",
|
|
3
|
+
"description": "A bordered accordion with several items, expanding one at a time.",
|
|
4
|
+
"html": "<nys-accordion bordered singleSelect>\n <nys-accordionitem heading=\"How do I apply?\" expanded>\n <p>Visit ny.gov and complete the online application.</p>\n </nys-accordionitem>\n <nys-accordionitem heading=\"What documents do I need?\">\n <p>You will need a valid ID and proof of residency.</p>\n </nys-accordionitem>\n <nys-accordionitem heading=\"How long does review take?\">\n <p>Most applications are reviewed within 10 business days.</p>\n </nys-accordionitem>\n</nys-accordion>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Tabs",
|
|
3
|
+
"description": "A tab group with three panels of related content.",
|
|
4
|
+
"html": "<nys-tabgroup>\n <nys-tab label=\"Marcy\"></nys-tab>\n <nys-tab label=\"Algonquin\"></nys-tab>\n <nys-tab label=\"Haystack\"></nys-tab>\n <nys-tabpanel>\n <p>Mount Marcy is the tallest peak in the Adirondacks, at 5,344 feet.</p>\n </nys-tabpanel>\n <nys-tabpanel>\n <p>Algonquin Peak is the second tallest, at 5,114 feet.</p>\n </nys-tabpanel>\n <nys-tabpanel>\n <p>Mount Haystack is the third tallest, at 4,960 feet.</p>\n </nys-tabpanel>\n</nys-tabgroup>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Modal",
|
|
3
|
+
"description": "A button opens a modal dialog with two action buttons that close it.",
|
|
4
|
+
"html": "<nys-button id=\"open-modal\" label=\"Open modal\"></nys-button>\n\n<nys-modal id=\"demo-modal\" heading=\"Update password?\">\n <p>You are about to update your account password. This cannot be undone.</p>\n <div slot=\"actions\">\n <nys-button id=\"cancel-modal\" label=\"Not now\" variant=\"outline\"></nys-button>\n <nys-button id=\"confirm-modal\" label=\"Update\"></nys-button>\n </div>\n</nys-modal>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const modal = document.getElementById('demo-modal');\n\ndocument.getElementById('open-modal').addEventListener('nys-click', () => {\n modal.open = true;\n});\n\ndocument.getElementById('cancel-modal').addEventListener('nys-click', () => {\n modal.open = false;\n});\n\ndocument.getElementById('confirm-modal').addEventListener('nys-click', () => {\n modal.open = false;\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Stepper",
|
|
3
|
+
"description": "A multi-step form sidebar that advances to the next step on a button click.",
|
|
4
|
+
"html": "<div class=\"nys-grid-row nys-grid-gap-300\">\n <nys-stepper id=\"demo-stepper\" label=\"Register for office hours\" class=\"nys-grid-col-12 nys-desktop:nys-grid-col-3\">\n <nys-step label=\"Personal details\" current></nys-step>\n <nys-step label=\"Team info\"></nys-step>\n <nys-step label=\"Usage survey\"></nys-step>\n <nys-step label=\"Newsletter opt-in\"></nys-step>\n </nys-stepper>\n <div class=\"nys-grid-col-12 nys-desktop:nys-grid-col-9\">\n <p id=\"step-content\">You are on step 1 of 4: Personal details.</p>\n <nys-button id=\"next-step\" label=\"Next step\"></nys-button>\n </div>\n</div>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const steps = Array.from(document.querySelectorAll('nys-step'));\nconst stepContent = document.getElementById('step-content');\nconst nextButton = document.getElementById('next-step');\n\nfunction advanceStep() {\n const currentIndex = steps.findIndex((step) => step.hasAttribute('current'));\n if (currentIndex === -1 || currentIndex === steps.length - 1) return;\n\n steps[currentIndex].removeAttribute('current');\n steps[currentIndex].setAttribute('previous', '');\n steps[currentIndex + 1].setAttribute('current', '');\n steps[currentIndex + 1].setAttribute('selected', '');\n\n const label = steps[currentIndex + 1].getAttribute('label');\n stepContent.textContent = `You are on step ${currentIndex + 2} of ${steps.length}: ${label}.`;\n\n if (currentIndex + 1 === steps.length - 1) {\n nextButton.disabled = true;\n }\n}\n\nnextButton.addEventListener('nys-click', advanceStep);\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Table and pagination",
|
|
3
|
+
"description": "A sortable table paired with pagination that updates a caption on page change.",
|
|
4
|
+
"html": "<nys-table id=\"peaks-table\" sortable striped bordered class=\"nys-margin-b-300\">\n <table>\n <caption>New York State high peaks</caption>\n <tr><th>Mountain</th><th>Peak height (ft)</th><th>Hike name</th></tr>\n <tr><td>Marcy</td><td>5,344</td><td>Van Hoevenberg Trail</td></tr>\n <tr><td>Algonquin</td><td>5,114</td><td>Northeast Trail</td></tr>\n <tr><td>Haystack</td><td>4,960</td><td>Johns Brook Trail</td></tr>\n <tr><td>Skylight</td><td>4,926</td><td>Lake Tear Trail</td></tr>\n </table>\n</nys-table>\n\n<nys-pagination id=\"peaks-pagination\" currentPage=\"1\" totalPages=\"5\"></nys-pagination>\n<p id=\"page-caption\">Showing page 1 of 5.</p>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const pagination = document.getElementById('peaks-pagination');\nconst caption = document.getElementById('page-caption');\n\npagination.addEventListener('nys-change', (e) => {\n caption.textContent = `Showing page ${e.detail.page} of ${pagination.totalPages}.`;\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Tooltip and dropdown menu",
|
|
3
|
+
"description": "A tooltip attached to a button, and a dropdown menu of actions.",
|
|
4
|
+
"html": "<div class=\"nys-display-flex nys-flex-align-center nys-flex-gap-300 nys-margin-b-400\">\n <nys-tooltip for=\"info-button\" text=\"This action cannot be undone.\"></nys-tooltip>\n <nys-button id=\"info-button\" label=\"Delete account\" variant=\"outline\"></nys-button>\n</div>\n\n<nys-button id=\"menu-trigger\" label=\"Open menu\"></nys-button>\n<nys-dropdownmenu id=\"account-menu\" for=\"menu-trigger\">\n <nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n <nys-dropdownmenuitem label=\"Settings\" href=\"/settings\"></nys-dropdownmenuitem>\n <nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n</nys-dropdownmenu>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Navigation",
|
|
3
|
+
"description": "Breadcrumbs, a vertical navigation menu with a collapsible group, and a process list.",
|
|
4
|
+
"html": "<nys-breadcrumbs class=\"nys-margin-b-400\">\n <ol>\n <li><a href=\"/\">Home</a></li>\n <li><a href=\"/government\">Government</a></li>\n <li>Parks & Recreation</li>\n </ol>\n</nys-breadcrumbs>\n\n<div class=\"nys-grid-row nys-grid-gap-400 nys-margin-b-400\">\n <div class=\"nys-grid-col-12 nys-desktop:nys-grid-col-4\">\n <nys-verticalnav heading=\"Freshwater fishing\" headingLevel=\"h2\">\n <ul>\n <li><a href=\"/\">Home</a></li>\n <li><a href=\"/services\">Services</a></li>\n <li>\n <nys-verticalnavgroup label=\"Regulations\">\n <ul>\n <li><a href=\"\">Places to fish</a></li>\n <li><a href=\"\">Learn to fish</a></li>\n <li><a href=\"\">Ice fishing</a></li>\n </ul>\n </nys-verticalnavgroup>\n </li>\n </ul>\n </nys-verticalnav>\n </div>\n</div>\n\n<nys-processlist id=\"application-steps\">\n <nys-processlistitem label=\"Gather your documents\" description=\"Recent pay stubs and a current property tax bill.\"></nys-processlistitem>\n <nys-processlistitem label=\"Complete the application\" description=\"Most applicants finish in about 20 minutes.\"></nys-processlistitem>\n <nys-processlistitem label=\"Submit and await review\"></nys-processlistitem>\n</nys-processlist>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Page structure",
|
|
3
|
+
"description": "The required NYSDS page skeleton: skip navigation, universal header, agency header, main content, back to top, and footers.",
|
|
4
|
+
"html": "<nys-skipnav></nys-skipnav>\n\n<nys-unavheader hideSearch hideTranslate></nys-unavheader>\n\n<nys-globalheader appName=\"Sample Application\" agencyName=\"Office of Information Technology Services\" homepageLink=\"/\">\n <ul>\n <li><a href=\"/services\">Services</a></li>\n <li><a href=\"/help\">Help center</a></li>\n <li><a href=\"/about\">About us</a></li>\n </ul>\n</nys-globalheader>\n\n<main id=\"main-content\">\n <div class=\"nys-grid-container nys-padding-y-400\">\n <h1>Page title</h1>\n <p>This is the main content area. Every page places its primary content inside a single main landmark.</p>\n </div>\n</main>\n\n<nys-backtotop visible></nys-backtotop>\n\n<footer>\n <nys-globalfooter agencyName=\"Office of Information Technology Services\" homepageLink=\"/\">\n <ul>\n <li><a href=\"/accessibility\">Accessibility</a></li>\n <li><a href=\"/privacy\">Privacy policy</a></li>\n </ul>\n </nys-globalfooter>\n <nys-unavfooter></nys-unavfooter>\n</footer>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Agency themes",
|
|
3
|
+
"description": "The same button, alert, and card under different agency themes. Themes come from the data-nys-theme attribute.",
|
|
4
|
+
"html": "<nys-select id=\"theme-select\" label=\"Select an agency theme\" class=\"nys-margin-b-300\">\n <option value=\"default\" label=\"Default (NY.gov)\" selected></option>\n <option value=\"admin\" label=\"Administration\"></option>\n <option value=\"health\" label=\"Health\"></option>\n <option value=\"transportation\" label=\"Transportation\"></option>\n <option value=\"environment\" label=\"Environment\"></option>\n</nys-select>\n\n<div id=\"theme-wrapper\">\n <div class=\"nys-display-flex nys-flex-column nys-flex-gap-300\">\n <nys-button label=\"Primary action\"></nys-button>\n <nys-alert type=\"info\" heading=\"Themed alert\" text=\"This alert's color follows the selected theme.\"></nys-alert>\n <nys-card heading=\"Themed card\" description=\"Card accents follow the theme color too.\"></nys-card>\n </div>\n</div>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": "const themeSelect = document.getElementById('theme-select');\nconst themeWrapper = document.getElementById('theme-wrapper');\n\nthemeSelect.addEventListener('nys-change', (e) => {\n themeWrapper.setAttribute('data-nys-theme', e.detail.value);\n});\n"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Utility classes",
|
|
3
|
+
"description": "A layout built only with NYSDS utility classes: grid, flex, spacing, and typography, with responsive prefixes.",
|
|
4
|
+
"html": "<div class=\"nys-grid-container\">\n <div class=\"nys-grid-row nys-grid-gap-300\">\n <div class=\"nys-grid-col-12 nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-4 nys-padding-300\">\n <p class=\"nys-font-h4\">Stacks on mobile</p>\n <p class=\"nys-font-body-sm\">This column is full width on mobile, half width on tablet, and a third on desktop.</p>\n </div>\n <div class=\"nys-grid-col-12 nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-4 nys-padding-300\">\n <p class=\"nys-font-h4\">Responsive by design</p>\n <p class=\"nys-font-body-sm\">Prefix any utility class with a breakpoint, such as nys-desktop, to change it at that size.</p>\n </div>\n <div class=\"nys-grid-col-12 nys-desktop:nys-grid-col-4 nys-padding-300\">\n <p class=\"nys-font-h4\">No custom CSS</p>\n <p class=\"nys-font-body-sm\">Every rule on this page comes from a utility class, not a stylesheet.</p>\n </div>\n </div>\n\n <div class=\"nys-display-flex nys-flex-column nys-tablet:nys-flex-row nys-flex-justify-space-between nys-flex-gap-200 nys-margin-t-400\">\n <span class=\"nys-font-ui-md\">Stacks on mobile, row on tablet</span>\n <span class=\"nys-font-ui-md\">Flex utilities control direction and gap</span>\n </div>\n</div>\n",
|
|
5
|
+
"css": "",
|
|
6
|
+
"js": ""
|
|
7
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Presets and decks
|
|
2
|
+
|
|
3
|
+
`presets/*.json` and `decks/*.json` are starter content. They aren't
|
|
4
|
+
loaded directly by the running app — the first time the playground opens
|
|
5
|
+
in a browser, it copies them into that browser's own deck store (see
|
|
6
|
+
`src/starters.ts`), and after that the app reads only from the store.
|
|
7
|
+
Every file in `presets/` becomes one slide of a starter deck called
|
|
8
|
+
**Component library**, in filename order. Every file in `decks/` becomes
|
|
9
|
+
its own starter deck. Selecting **Restore starter decks** on the home
|
|
10
|
+
page adds back any starter deck a browser is missing, including changes
|
|
11
|
+
you make here after rebuilding.
|
|
12
|
+
|
|
13
|
+
## Preset schema
|
|
14
|
+
|
|
15
|
+
Each file in `presets/` is a JSON object with these fields.
|
|
16
|
+
|
|
17
|
+
| Field | Type | Required | Description |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| `title` | string | yes | Short name shown in the slide list and the presentation caption. |
|
|
20
|
+
| `description` | string | yes | One sentence shown as the presentation caption. |
|
|
21
|
+
| `html` | string | yes | Body markup only. The app wraps it with the head that loads NYSDS. |
|
|
22
|
+
| `css` | string | yes | Custom styles for the preview. Use an empty string if none. |
|
|
23
|
+
| `js` | string | yes | An ES module that runs in the preview. Use an empty string if none. |
|
|
24
|
+
| `group` | string | no | A section label shown in the caption, such as `1. Lock it down`. |
|
|
25
|
+
| `notes` | string | no | Presenter notes. Press `n` to read them. Never shown in the preview. |
|
|
26
|
+
| `version` | string | no | An NYSDS version to pin this slide to. Omit it, or use `latest`, to follow the app's default version. |
|
|
27
|
+
| `editors` | string array | no | Which columns to expand in the side-by-side layout, for example `["html", "css"]`. Columns left out start collapsed. Ignored in the tabs layout. |
|
|
28
|
+
|
|
29
|
+
Don't put an `id` field in a file in this directory. The id comes from
|
|
30
|
+
the filename instead.
|
|
31
|
+
|
|
32
|
+
## Naming and ordering
|
|
33
|
+
|
|
34
|
+
Name files `NN-slug.json`, for example `01-button.json` or
|
|
35
|
+
`12-form-validation.json`. The numeric prefix sets the order slides
|
|
36
|
+
appear in the Component library deck. The slug becomes the slide's id.
|
|
37
|
+
|
|
38
|
+
## Author in the browser, then export
|
|
39
|
+
|
|
40
|
+
There's no separate build step for a preset, so the fastest way to write
|
|
41
|
+
one is to shape it as a deck in the running app, then pull the slide back
|
|
42
|
+
out.
|
|
43
|
+
|
|
44
|
+
1. On the home page, select **Scratch pad**, or open any deck and add a
|
|
45
|
+
slide.
|
|
46
|
+
2. Use the HTML, CSS, and JS editors to build the example, and **Slide
|
|
47
|
+
settings** to set its title, description, group, notes, version, and
|
|
48
|
+
starting columns.
|
|
49
|
+
3. From the scratch pad, select **Save as deck** first, since only a
|
|
50
|
+
saved deck can be exported.
|
|
51
|
+
4. Select **Export deck** in the toolbar. It downloads a JSON file shaped
|
|
52
|
+
like [Decks](#decks), below, with one slide in its `presets` array.
|
|
53
|
+
5. Copy that one slide object out of the `presets` array, delete its
|
|
54
|
+
`id` field, and save the rest as `presets/NN-slug.json`.
|
|
55
|
+
6. Rebuild, or select **Restore starter decks** in a browser that already
|
|
56
|
+
seeded, to pick up the new file.
|
|
57
|
+
|
|
58
|
+
## Decks
|
|
59
|
+
|
|
60
|
+
A deck bundles several slides into one presentation, with its own title
|
|
61
|
+
and description. Add a starter deck by creating `decks/<id>.json`; the
|
|
62
|
+
filename without its extension becomes the deck's id.
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"title": "Customizing components",
|
|
67
|
+
"description": "One sentence describing the deck.",
|
|
68
|
+
"boilerplate": {
|
|
69
|
+
"baseCss": "body { padding: 2rem; }"
|
|
70
|
+
},
|
|
71
|
+
"presets": [
|
|
72
|
+
{
|
|
73
|
+
"id": "01-header-drop-in",
|
|
74
|
+
"group": "1. Lock it down",
|
|
75
|
+
"title": "Drop in the header",
|
|
76
|
+
"notes": "Presenter-only notes for this slide.",
|
|
77
|
+
"html": "<nys-globalheader appName=\"Example\" nysLogo></nys-globalheader>",
|
|
78
|
+
"css": "",
|
|
79
|
+
"js": ""
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
A deck's `presets` array holds full slide objects, using the same fields
|
|
86
|
+
as the preset schema, with one difference: each slide needs its own `id`,
|
|
87
|
+
because it isn't loaded from a file of its own. `boilerplate.baseCss` is
|
|
88
|
+
CSS injected into the hidden preview head for every slide in the deck —
|
|
89
|
+
use it for shared layout, such as the `.stage` and `.card` helper classes
|
|
90
|
+
in `decks/customizing-components.json`. Don't set `boilerplate.head`: the
|
|
91
|
+
playground ignores it and logs a console warning, because the version
|
|
92
|
+
selector, not the deck, controls what the preview loads.
|
|
93
|
+
|
|
94
|
+
Building a starter deck is simpler than building a preset, because
|
|
95
|
+
**Export deck** already writes this exact shape: create the deck in the
|
|
96
|
+
app, add and arrange its slides, select **Export deck**, and move the
|
|
97
|
+
downloaded file into `decks/` under the filename you want as its id.
|
|
98
|
+
`decks/customizing-components.json` is a full worked example.
|
|
99
|
+
|
|
100
|
+
## Validation tips
|
|
101
|
+
|
|
102
|
+
- Run `npm run build` after adding a preset or a deck. `tsc --noEmit`
|
|
103
|
+
catches malformed JSON and a broken build catches most other mistakes.
|
|
104
|
+
- Check every component attribute you use against
|
|
105
|
+
`mcp__nysds__validate_component_api` before committing a preset. Don't
|
|
106
|
+
read `node_modules/@nysds` for this — use the NYSDS MCP server.
|
|
107
|
+
- Keep examples short. Presentation mode puts the editors in a drawer
|
|
108
|
+
over the bottom of the preview, and a slide that needs scrolling to
|
|
109
|
+
read from the back of a room is too long.
|
|
110
|
+
|
|
111
|
+
## Icons
|
|
112
|
+
|
|
113
|
+
NYSDS ships only a curated subset of Material Symbols. An icon name
|
|
114
|
+
outside that set renders as empty space. Check the list at
|
|
115
|
+
https://designsystem.ny.gov/components/icon/ (mirrored in
|
|
116
|
+
`src/icon-names.ts`) before using `icon`, `prefixIcon`, `suffixIcon`,
|
|
117
|
+
or `<nys-icon name>`. `npm test` fails on unknown icon names in any
|
|
118
|
+
preset or deck.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="66" height="66" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<mask id="mask0_2_15" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="66" height="66">
|
|
3
|
+
<circle cx="33" cy="33" r="33" fill="#286AD8"/>
|
|
4
|
+
</mask>
|
|
5
|
+
<g mask="url(#mask0_2_15)">
|
|
6
|
+
<circle cx="33" cy="33" r="33" fill="#356CB0"/>
|
|
7
|
+
<path d="M78 43.5L51 15L14 24.5L25 34L-1 59.5L30.5 94L78 43.5Z" fill="#001842"/>
|
|
8
|
+
<path d="M34.5 24.5L0 58.5L7.5 65.5L41 31.5V51H51V15H14V24.5H34.5Z" fill="white"/>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<svg width="1037" height="114" viewBox="0 0 1037 114" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M173.465 90.3263L135.28 36.532V90.3263H118.229V10.2351H135.761L172.865 62.1088V10.2351H189.916V90.3263H173.465Z" fill="#1B1B1B"/>
|
|
3
|
+
<path d="M223.538 90.3263V57.545L192.679 10.2351H212.131L232.064 42.4161L251.757 10.2351H271.209L240.589 57.545V90.3263H223.538Z" fill="#1B1B1B"/>
|
|
4
|
+
<path d="M274.572 66.071C280.216 71.9551 288.982 76.8783 300.029 76.8783C309.395 76.8783 313.957 72.4343 313.957 67.8718C313.957 61.8679 306.994 59.8262 297.748 57.6648C284.659 54.6635 267.848 51.0606 267.848 33.17C267.848 19.8418 279.375 9.03455 298.228 9.03455C310.956 9.03455 321.522 12.877 329.447 20.2012L319.961 32.6895C313.477 26.6856 304.832 23.9239 297.026 23.9239C289.341 23.9239 285.259 27.2858 285.259 32.0892C285.259 37.4929 291.983 39.1739 301.229 41.3353C314.438 44.3366 331.249 48.2989 331.249 66.071C331.249 80.7194 320.802 91.7676 299.188 91.7676C283.818 91.7676 272.771 86.6036 265.206 79.0385L274.572 66.071Z" fill="#1B1B1B"/>
|
|
5
|
+
<path d="M360.259 90.3262V11.6738H387.145C411.555 11.6738 427.473 28.7715 427.473 51.0592C427.473 73.4642 411.555 90.3262 387.145 90.3262H360.259ZM370.047 81.5996H387.145C406.248 81.5996 417.332 67.9212 417.332 51.0592C417.332 34.0788 406.602 20.3991 387.145 20.3991H370.047V81.5996Z" fill="#1B1B1B"/>
|
|
6
|
+
<path d="M460.963 31.9564C478.179 31.9564 488.321 45.3991 488.321 62.4968V64.7377H442.214C442.921 75.4681 450.468 84.4304 462.732 84.4304C469.218 84.4304 475.821 81.8366 480.302 77.2377L484.547 83.015C478.887 88.6752 471.222 91.7416 461.907 91.7416C445.043 91.7416 432.897 79.5957 432.897 61.7898C432.897 45.2806 444.69 31.9564 460.963 31.9564ZM442.214 58.252H479.594C479.477 49.7611 473.817 39.2663 460.845 39.2663C448.7 39.2663 442.685 49.5254 442.214 58.252Z" fill="#1B1B1B"/>
|
|
7
|
+
<path d="M496.338 76.4122C500.111 80.7741 507.304 84.5476 515.086 84.5476C523.813 84.5476 528.529 80.6569 528.529 75.114C528.529 68.8653 521.572 66.8601 513.907 64.9734C504.237 62.7325 493.271 60.1387 493.271 48.347C493.271 39.5033 500.935 31.9564 514.497 31.9564C524.166 31.9564 531.006 35.6114 535.605 40.2103L531.477 46.3418C528.058 42.2142 521.808 39.1491 514.497 39.1491C506.714 39.1491 501.879 42.6869 501.879 47.7572C501.879 53.2989 508.365 55.0684 515.793 56.8366C525.7 59.0775 537.137 61.9069 537.137 74.5254C537.137 84.0762 529.473 91.7416 514.732 91.7416C505.417 91.7416 497.516 88.9109 491.739 82.7793L496.338 76.4122Z" fill="#1B1B1B"/>
|
|
8
|
+
<path d="M544.921 17.8054C544.921 14.5033 547.633 11.9095 550.817 11.9095C554.119 11.9095 556.831 14.5033 556.831 17.8054C556.831 21.1075 554.119 23.8197 550.817 23.8197C547.633 23.8197 544.921 21.1075 544.921 17.8054ZM546.453 90.3262V33.3705H555.297V90.3262H546.453Z" fill="#1B1B1B"/>
|
|
9
|
+
<path d="M571.569 98.3444C576.285 104.005 581.947 106.127 590.082 106.127C599.516 106.127 608.361 101.528 608.361 89.0293V80.8926C604.233 86.6713 597.276 91.0332 589.257 91.0332C574.4 91.0332 563.904 79.9486 563.904 61.5541C563.904 43.2767 574.281 31.9564 589.257 31.9564C596.922 31.9564 603.762 35.7299 608.361 41.9786V33.3705H617.205V88.6752C617.205 107.542 603.998 113.438 590.082 113.438C580.413 113.438 573.81 111.551 567.089 104.949L571.569 98.3444ZM608.361 49.0541C605.294 44.1023 598.455 39.8562 591.379 39.8562C579.942 39.8562 573.102 48.9369 573.102 61.5541C573.102 74.0528 579.942 83.2507 591.379 83.2507C598.455 83.2507 605.294 78.8874 608.361 73.9356V49.0541Z" fill="#1B1B1B"/>
|
|
10
|
+
<path d="M666.376 90.3262V53.0632C666.376 43.0398 661.305 39.8562 653.641 39.8562C646.684 39.8562 640.079 44.1023 636.777 48.6999V90.3262H627.934V33.3705H636.777V41.6257C640.788 36.9082 648.57 31.9564 657.06 31.9564C668.97 31.9564 675.22 37.9694 675.22 50.351V90.3262H666.376Z" fill="#1B1B1B"/>
|
|
11
|
+
<path d="M705.878 71.8132C711.067 77.5905 719.557 83.015 730.641 83.015C744.674 83.015 749.154 75.4681 749.154 69.4538C749.154 60.0202 739.604 57.4264 729.226 54.597C716.609 51.2949 702.576 47.7572 702.576 32.3092C702.576 19.3379 714.132 10.4941 729.58 10.4941C741.607 10.4941 750.924 14.5033 757.527 21.4616L751.631 28.6543C745.735 22.1686 737.481 19.2207 728.873 19.2207C719.439 19.2207 712.718 24.291 712.718 31.7194C712.718 39.6204 721.798 41.9785 731.821 44.6908C744.674 48.1113 759.296 52.1204 759.296 68.6283C759.296 80.0671 751.514 91.7415 730.287 91.7415C716.609 91.7415 706.585 86.5527 700.1 79.2415L705.878 71.8132Z" fill="#1B1B1B"/>
|
|
12
|
+
<path d="M764.249 104.594C765.546 105.184 767.668 105.538 769.083 105.538C772.974 105.538 775.569 104.24 777.573 99.5241L781.346 90.9161L757.527 33.3705H767.078L786.064 80.0671L804.931 33.3705H814.6L786.064 101.882C782.645 110.136 776.866 113.321 769.319 113.438C767.432 113.438 764.484 113.085 762.833 112.613L764.249 104.594Z" fill="#1B1B1B"/>
|
|
13
|
+
<path d="M818.608 76.4122C822.382 80.7741 829.576 84.5476 837.358 84.5476C846.085 84.5476 850.801 80.6569 850.801 75.114C850.801 68.8653 843.844 66.8601 836.179 64.9734C826.509 62.7325 815.543 60.1387 815.543 48.347C815.543 39.5033 823.207 31.9564 836.769 31.9564C846.438 31.9564 853.278 35.6114 857.877 40.2103L853.749 46.3418C850.33 42.2142 844.08 39.1491 836.769 39.1491C828.986 39.1491 824.151 42.6869 824.151 47.7572C824.151 53.2989 830.637 55.0684 838.065 56.8366C847.972 59.0775 859.409 61.9069 859.409 74.5254C859.409 84.0762 851.745 91.7416 837.004 91.7416C827.689 91.7416 819.788 88.9109 814.011 82.7793L818.608 76.4122Z" fill="#1B1B1B"/>
|
|
14
|
+
<path d="M872.262 78.4161V41.1531H862.828V33.3705H872.262V17.8054H881.105V33.3705H892.661V41.1531H881.105V76.5294C881.105 80.7742 882.992 83.8406 886.883 83.8406C889.359 83.8406 891.717 82.7794 892.897 81.4825L895.491 88.0854C893.251 90.2078 890.068 91.7416 884.879 91.7416C876.507 91.7416 872.262 86.907 872.262 78.4161Z" fill="#1B1B1B"/>
|
|
15
|
+
<path d="M924.499 31.9564C941.715 31.9564 951.857 45.3991 951.857 62.4968V64.7377H905.75C906.457 75.4681 914.004 84.4304 926.268 84.4304C932.754 84.4304 939.357 81.8366 943.839 77.2377L948.083 83.015C942.423 88.6752 934.758 91.7416 925.443 91.7416C908.579 91.7416 896.434 79.5957 896.434 61.7898C896.434 45.2806 908.227 31.9564 924.499 31.9564ZM905.75 58.252H943.13C943.013 49.7611 937.353 39.2663 924.382 39.2663C912.236 39.2663 906.221 49.5254 905.75 58.252Z" fill="#1B1B1B"/>
|
|
16
|
+
<path d="M1028.15 90.3262V51.6491C1028.15 44.4551 1024.97 39.8562 1017.65 39.8562C1011.76 39.8562 1005.51 44.1023 1002.56 48.5827V90.3262H993.717V51.6491C993.717 44.4551 990.651 39.8562 983.223 39.8562C977.444 39.8562 971.312 44.1023 968.246 48.6999V90.3262H959.402V33.3705H968.246V41.6257C970.605 37.9694 978.27 31.9564 986.642 31.9564C995.368 31.9564 1000.32 36.6726 1001.97 42.5684C1005.15 37.3796 1012.82 31.9564 1021.07 31.9564C1031.45 31.9564 1036.99 37.7338 1036.99 49.1726V90.3262H1028.15Z" fill="#1B1B1B"/>
|
|
17
|
+
<path d="M102 51C102 79.1665 79.1665 102 51 102C22.8335 102 0 79.1665 0 51C0 22.8335 22.8335 0 51 0C79.1665 0 102 22.8335 102 51Z" fill="white"/>
|
|
18
|
+
<path d="M38.143 53.6836L21.5618 37.0961V22.6247H79.4254L101.645 44.998C98.6661 19.6592 77.1299 0 51 0C22.8335 0 0 22.842 0 51.0189C0 62.5071 3.79756 73.1065 10.2025 81.6347" fill="#245FC2"/>
|
|
19
|
+
<path d="M79.4254 22.5866V80.4719H64.9597V47.2844L20.4358 91.825C28.9535 98.2138 39.5345 102 51 102C79.1663 102 102 79.1581 102 50.9809C102 48.9382 101.866 46.9279 101.633 44.948L79.4254 22.5866Z" fill="#0E324F"/>
|
|
20
|
+
<path d="M21.559 37.0958H54.7212L38.1402 53.6832L21.559 37.0958Z" fill="#0E324F"/>
|
|
21
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="13 3 205 205" width="205" height="205" fill="currentColor" aria-hidden="true" focusable="false">
|
|
2
|
+
<!-- The NYSDS symbol as a single-color mark. The arrow is cut out, so the
|
|
3
|
+
surface behind it shows through. Derived from nysds-logo.svg. -->
|
|
4
|
+
<path d="M89.6599 110.894L56.3349 77.5558V48.4713H172.629L217.285 93.4372C211.299 42.5111 168.016 3 115.5 3C58.8907 3 13 48.908 13 105.538C13 128.627 20.6323 149.93 33.5051 167.07"/>
|
|
5
|
+
<path d="M172.629 48.3945V164.733H143.556V98.0323L54.072 187.55C71.191 200.39 92.4567 208 115.5 208C172.109 208 218 162.092 218 105.462C218 101.356 217.731 97.3158 217.262 93.3366L172.629 48.3945Z"/>
|
|
6
|
+
<path d="M56.3291 77.5552H122.979L89.6541 110.893L56.3291 77.5552Z"/>
|
|
7
|
+
</svg>
|