|
91 | 91 |
|
92 | 92 | <svelte:window on:copysuccess={copySuccess} /> |
93 | 93 |
|
94 | | -<div class="d-flex"> |
95 | | - <div class="fl-grow1 p24 wmn0"> |
96 | | - <TextInput |
97 | | - id="icon-search" |
98 | | - label="Search icons and spots" |
99 | | - hideLabel |
100 | | - type="search" |
101 | | - placeholder="Search icons and spots…" |
102 | | - bind:value={search} |
103 | | - /> |
104 | | -
|
105 | | - {#snippet section(label, entries)} |
106 | | - {#if entries.length > 0} |
107 | | - <h2 class="fs-title fw-bold mt32 mb12"> |
108 | | - {label} <span class="s-badge ml4">{entries.length}</span> |
109 | | - </h2> |
110 | | -
|
111 | | - <div class="icons-grid"> |
112 | | - {#each entries as entry (entry.name)} |
113 | | - {@const def = getDefaultVariant(entry)} |
114 | | - <button |
115 | | - class="c-pointer h:bg-black-100 s-btn s-btn__unset p12 d-flex fd-column h100 {selected?.name === entry.name ? 'bg-blue-100' : ''}" |
116 | | - onclick={() => selectEntry(entry)} |
117 | | - > |
118 | | - <div class="d-flex ai-center jc-center my-auto h100"> |
119 | | - <!-- eslint-disable-next-line svelte/no-at-html-tags --> |
120 | | - {@html def.svg.replace('class="', `class="w100 h-auto wmx100 ${label === 'Spots' ? 'native' : ''} `)} |
121 | | - </div> |
122 | | - <div class="fs-fine mt-auto pt8"> |
123 | | - {entry.name} |
124 | | - </div> |
125 | | - </button> |
126 | | - {/each} |
127 | | - </div> |
128 | | - {/if} |
129 | | - {/snippet} |
130 | | -
|
131 | | - {@render section('Icons', filteredIcons)} |
132 | | - {@render section('Spots', filteredSpots)} |
133 | | - </div> |
134 | | -
|
135 | | - <aside class="ws3 ps-sticky md:ps-fixed z-nav bg-white t0 r0 overflow-y-scroll fl-shrink0 bl bc-black-200 h-screen {!(selected && selectedVariant) ? 'md:d-none' : ''} "> |
136 | | - {#if selected && selectedVariant} |
137 | | - <div class="d-flex fd-column bb bc-black-200 hs3"> |
138 | | - <div class="d-flex jc-space-between px12"> |
139 | | - <button onclick={() => selected = null} type="button" title="Close inspector" class="d-none md:d-block px4 s-btn s-btn__sm s-btn__clear s-btn__icon"> |
140 | | - <Icon src={IconCross} /> |
| 94 | +<div class="fl-grow1 p24 wmn0"> |
| 95 | + <TextInput |
| 96 | + id="icon-search" |
| 97 | + label="Search icons and spots" |
| 98 | + hideLabel |
| 99 | + type="search" |
| 100 | + placeholder="Search icons and spots…" |
| 101 | + bind:value={search} |
| 102 | + /> |
| 103 | +
|
| 104 | + {#snippet section(label, entries)} |
| 105 | + {#if entries.length > 0} |
| 106 | + <h2 class="fs-title fw-bold mt32 mb12"> |
| 107 | + {label} <span class="s-badge ml4">{entries.length}</span> |
| 108 | + </h2> |
| 109 | +
|
| 110 | + <div class="icons-grid"> |
| 111 | + {#each entries as entry (entry.name)} |
| 112 | + {@const def = getDefaultVariant(entry)} |
| 113 | + <button |
| 114 | + class="c-pointer h:bg-black-100 s-btn s-btn__unset p12 d-flex fd-column h100 {selected?.name === entry.name ? 'bg-blue-100' : ''}" |
| 115 | + onclick={() => selectEntry(entry)} |
| 116 | + > |
| 117 | + <div class="d-flex ai-center jc-center my-auto h100"> |
| 118 | + <!-- eslint-disable-next-line svelte/no-at-html-tags --> |
| 119 | + {@html def.svg.replace('class="', `class="w100 h-auto wmx100 ${label === 'Spots' ? 'native' : ''} `)} |
| 120 | + </div> |
| 121 | + <div class="fs-fine mt-auto pt8"> |
| 122 | + {entry.name} |
| 123 | + </div> |
141 | 124 | </button> |
142 | | -
|
143 | | - <h3 class="fs-title fw-bold lh-sm mb0 p16 ta-center fl1 md:ta-left">{selected.name}</h3> |
144 | | - </div> |
145 | | -
|
146 | | - <div class="h100 d-flex bg-white d:bg-black"> |
147 | | - <!-- eslint-disable-next-line svelte/no-at-html-tags --> |
148 | | - {@html selectedVariant.svg.replace('class="', 'class="native m-auto ')} |
149 | | - </div> |
| 125 | + {/each} |
150 | 126 | </div> |
| 127 | + {/if} |
| 128 | + {/snippet} |
151 | 129 |
|
152 | | - <div class="d-flex jc-space-between ai-center bg-black-100 bb bc-black-200 py6 px16"> |
153 | | - {exportName} |
| 130 | + {@render section('Icons', filteredIcons)} |
| 131 | + {@render section('Spots', filteredSpots)} |
| 132 | +</div> |
154 | 133 |
|
155 | | - <button type="button" title="Copy name" data-copy-id="name" class="px4 ml-auto s-btn s-btn__sm s-btn__clear s-btn__icon" use:copyToClipboard={exportName}> |
156 | | - {#if copied === 'name'} |
157 | | - <Icon src={IconCheckFillCircle} class="fc-green-400" /> |
158 | | - {:else} |
159 | | - <Icon src={IconStackCards} /> |
160 | | - {/if} |
| 134 | +<aside class="ws3 ps-sticky md:ps-fixed z-nav bg-white t0 r0 overflow-y-scroll fl-shrink0 bl bc-black-200 h-screen {!(selected && selectedVariant) ? 'd-none' : ''} "> |
| 135 | + {#if selected && selectedVariant} |
| 136 | + <div class="d-flex fd-column bb bc-black-200 hs3"> |
| 137 | + <div class="d-flex jc-space-between px12"> |
| 138 | + <button onclick={() => selected = null} type="button" title="Close inspector" class="d-none md:d-block px4 s-btn s-btn__sm s-btn__clear s-btn__icon"> |
| 139 | + <Icon src={IconCross} /> |
161 | 140 | </button> |
162 | 141 |
|
163 | | - <Button title="Open in Figma" size="sm" weight="clear" icon href={selectedVariant.figmaUrl} class="px4"> |
164 | | - <Icon src={IconServiceFigma} class="native" /> |
165 | | - </Button> |
| 142 | + <h3 class="fs-title fw-bold lh-sm mb0 p16 ta-center fl1 md:ta-left">{selected.name}</h3> |
166 | 143 | </div> |
167 | 144 |
|
168 | | - {#each variants as variant (variant.key)} |
169 | | - <div class="py16 px16 bb bc-black-200"> |
170 | | - <p class="section-label tt-uppercase fw-semibold fc-black-400 mb8 fl1">{variant.key}</p> |
171 | | - <div class="d-flex g4 fw-wrap"> |
172 | | - {#each variant.values as val (val)} |
173 | | - {@const isActive = selectedProps[variant.key] === val} |
174 | | - {@const compatible = isCompatible(variant.key, val)} |
175 | | -
|
176 | | - <button |
177 | | - type="button" |
178 | | - disabled={!compatible} |
179 | | - class="s-btn s-btn__unset py2 px4 {isActive ? 'bg-blue-200 fc-blue-600' : compatible && 'c-pointer h:bg-black-200'} {!compatible ? 'c-not-allowed fc-black-300 bg-black-100' : ''}" |
180 | | - onclick={() => setDimension(variant.key, val)} |
181 | | - >{val}</button> |
182 | | - {/each} |
183 | | - </div> |
184 | | - </div> |
185 | | - {/each} |
186 | | -
|
187 | | - <div class="mb16"> |
188 | | - <p class="section-label tt-uppercase fw-semibold fc-black-400 mb8 pt16 px16">Usage</p> |
189 | | -
|
190 | | - <Navigation label="Base"> |
191 | | - {#each ["Svelte", ".NET", "SVG"] as label (label)} |
192 | | - <NavigationItem |
193 | | - text={label} |
194 | | - selected={activeCodeTab === label} |
195 | | - onclick={() => activeCodeTab = label} |
196 | | - /> |
| 145 | + <div class="h100 d-flex bg-white d:bg-black"> |
| 146 | + <!-- eslint-disable-next-line svelte/no-at-html-tags --> |
| 147 | + {@html selectedVariant.svg.replace('class="', 'class="native m-auto ')} |
| 148 | + </div> |
| 149 | + </div> |
| 150 | +
|
| 151 | + <div class="d-flex jc-space-between ai-center bg-black-100 bb bc-black-200 py6 px16"> |
| 152 | + {exportName} |
| 153 | +
|
| 154 | + <button type="button" title="Copy name" data-copy-id="name" class="px4 ml-auto s-btn s-btn__sm s-btn__clear s-btn__icon" use:copyToClipboard={exportName}> |
| 155 | + {#if copied === 'name'} |
| 156 | + <Icon src={IconCheckFillCircle} class="fc-green-400" /> |
| 157 | + {:else} |
| 158 | + <Icon src={IconStackCards} /> |
| 159 | + {/if} |
| 160 | + </button> |
| 161 | +
|
| 162 | + <Button title="Open in Figma" size="sm" weight="clear" icon href={selectedVariant.figmaUrl} class="px4"> |
| 163 | + <Icon src={IconServiceFigma} class="native" /> |
| 164 | + </Button> |
| 165 | + </div> |
| 166 | +
|
| 167 | + {#each variants as variant (variant.key)} |
| 168 | + <div class="py16 px16 bb bc-black-200"> |
| 169 | + <p class="section-label tt-uppercase fw-semibold fc-black-400 mb8 fl1">{variant.key}</p> |
| 170 | + <div class="d-flex g4 fw-wrap"> |
| 171 | + {#each variant.values as val (val)} |
| 172 | + {@const isActive = selectedProps[variant.key] === val} |
| 173 | + {@const compatible = isCompatible(variant.key, val)} |
| 174 | +
|
| 175 | + <button |
| 176 | + type="button" |
| 177 | + disabled={!compatible} |
| 178 | + class="s-btn s-btn__unset py2 px4 {isActive ? 'bg-blue-200 fc-blue-600' : compatible && 'c-pointer h:bg-black-200'} {!compatible ? 'c-not-allowed fc-black-300 bg-black-100' : ''}" |
| 179 | + onclick={() => setDimension(variant.key, val)} |
| 180 | + >{val}</button> |
197 | 181 | {/each} |
198 | | - </Navigation> |
| 182 | + </div> |
| 183 | + </div> |
| 184 | + {/each} |
199 | 185 |
|
200 | | - {#if activeCodeTab === 'Svelte'} |
201 | | - <p class="m16 fs-caption">If you are working in a Svelte project, you can use the <code>Icon</code> component to render the asset as an <code>svg</code> element with the appropriate classes and attributes (<a href="https://svelte.stackoverflow.design/?path=/docs/components-icon--docs" class="s-link">docs</a>).</p> |
| 186 | + <div class="mb16"> |
| 187 | + <p class="section-label tt-uppercase fw-semibold fc-black-400 mb8 pt16 px16">Usage</p> |
202 | 188 |
|
203 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
204 | | - import { Icon } from '@stackoverflow/stacks-svelte'; |
205 | | - </code> |
| 189 | + <Navigation label="Base"> |
| 190 | + {#each ["Svelte", ".NET", "SVG"] as label (label)} |
| 191 | + <NavigationItem |
| 192 | + text={label} |
| 193 | + selected={activeCodeTab === label} |
| 194 | + onclick={() => activeCodeTab = label} |
| 195 | + /> |
| 196 | + {/each} |
| 197 | + </Navigation> |
206 | 198 |
|
207 | | - <p class="m16 fs-caption">Import this asset</p> |
| 199 | + {#if activeCodeTab === 'Svelte'} |
| 200 | + <p class="m16 fs-caption">If you are working in a Svelte project, you can use the <code>Icon</code> component to render the asset as an <code>svg</code> element with the appropriate classes and attributes (<a href="https://svelte.stackoverflow.design/?path=/docs/components-icon--docs" class="s-link">docs</a>).</p> |
208 | 201 |
|
209 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
210 | | - import { {selected?.isSpot ? 'Spot' : 'Icon'}{exportName} } from "@stackoverflow/stacks-icons/{selected?.isSpot ? 'spots' : 'icons'}"; |
211 | | - </code> |
| 202 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 203 | + import { Icon } from '@stackoverflow/stacks-svelte'; |
| 204 | + </code> |
212 | 205 |
|
213 | | - <p class="m16 fs-caption">Render this asset</p> |
| 206 | + <p class="m16 fs-caption">Import this asset</p> |
214 | 207 |
|
215 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
216 | | - <Icon src={{selected?.isSpot ? 'Spot' : 'Icon'}{exportName}} /> |
217 | | - </code> |
218 | | - {/if} |
219 | | - {#if activeCodeTab === '.NET'} |
220 | | - <p class="m16 fs-caption">If you’re working in a .NET project, we have a helper that can be called with <code>@Svg.</code> and the icon name. By default, any icon will inherit the text color of the parent element.</p> |
| 208 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 209 | + import { {selected?.isSpot ? 'Spot' : 'Icon'}{exportName} } from "@stackoverflow/stacks-icons/{selected?.isSpot ? 'spots' : 'icons'}"; |
| 210 | + </code> |
221 | 211 |
|
222 | | - <p class="m16 fs-caption">Add the helper</p> |
| 212 | + <p class="m16 fs-caption">Render this asset</p> |
223 | 213 |
|
224 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
225 | | - @inject IModuleSvg Svg |
226 | | - </code> |
| 214 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 215 | + <Icon src={{selected?.isSpot ? 'Spot' : 'Icon'}{exportName}} /> |
| 216 | + </code> |
| 217 | + {/if} |
| 218 | + {#if activeCodeTab === '.NET'} |
| 219 | + <p class="m16 fs-caption">If you’re working in a .NET project, we have a helper that can be called with <code>@Svg.</code> and the icon name. By default, any icon will inherit the text color of the parent element.</p> |
227 | 220 |
|
228 | | - <p class="m16 fs-caption">Render the asset</p> |
| 221 | + <p class="m16 fs-caption">Add the helper</p> |
229 | 222 |
|
230 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
231 | | - @Svg.{selectedVariant.key} |
232 | | - </code> |
| 223 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 224 | + @inject IModuleSvg Svg |
| 225 | + </code> |
233 | 226 |
|
234 | | - <p class="m16 fs-caption">Add CSS classes as a string:</p> |
| 227 | + <p class="m16 fs-caption">Render the asset</p> |
235 | 228 |
|
236 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
237 | | - @Svg.{selected?.isSpot ? 'Spot' : ''}{selectedVariant.key}.With("native fc-black-300") |
238 | | - </code> |
| 229 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 230 | + @Svg.{selectedVariant.key} |
| 231 | + </code> |
239 | 232 |
|
240 | | - <p class="m16 fs-caption">You can also add a <code>title</code> prop, which also removes <code>aria-hidden</code>.</p> |
| 233 | + <p class="m16 fs-caption">Add CSS classes as a string:</p> |
241 | 234 |
|
242 | | - <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
243 | | - @Svg.{selected?.isSpot ? 'Spot' : ''}{selectedVariant.key}.With(cssClass: "fc-danger", title: "foo") |
244 | | - </code> |
245 | | - {/if} |
246 | | - {#if activeCodeTab === 'SVG'} |
247 | | - <button type="button" title="Copy SVG" data-copy-id="svg" class="m12 mb0 s-btn s-btn__sm s-btn__clear s-btn__icon" use:copyToClipboard={selectedVariant.svg}> |
248 | | - {#if copied === 'svg'} |
249 | | - <Icon src={IconCheckFillCircle} class="fc-green-400" /> Copied SVG! |
250 | | - {:else} |
251 | | - <Icon src={IconStackCards} /> Copy SVG |
252 | | - {/if} |
253 | | - </button> |
| 235 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 236 | + @Svg.{selected?.isSpot ? 'Spot' : ''}{selectedVariant.key}.With("native fc-black-300") |
| 237 | + </code> |
254 | 238 |
|
255 | | - <TextArea size="sm" class="m12 hs2 ff-mono" id="asset-svg-code" label="SVG" hideLabel readonly value={selectedVariant.svg} /> |
256 | | - {/if} |
257 | | - </div> |
| 239 | + <p class="m16 fs-caption">You can also add a <code>title</code> prop, which also removes <code>aria-hidden</code>.</p> |
258 | 240 |
|
259 | | - <div class="fs-caption px16 pb16 fc-black-400"> |
260 | | - <b>Asset last updated:</b><br/> |
261 | | - <time datetime={selectedVariant.updatedAt}> |
262 | | - {new Date(selectedVariant.updatedAt).toLocaleDateString('en-US', { |
263 | | - year: 'numeric', |
264 | | - month: 'short', |
265 | | - day: 'numeric', |
266 | | - hour: 'numeric', |
267 | | - minute: 'numeric', |
268 | | - })} |
269 | | - </time> |
270 | | - </div> |
271 | | - {/if} |
272 | | - </aside> |
273 | | -</div> |
| 241 | + <code class="d-block bg-black-100 ow-anywhere py12 px16 fs-caption"> |
| 242 | + @Svg.{selected?.isSpot ? 'Spot' : ''}{selectedVariant.key}.With(cssClass: "fc-danger", title: "foo") |
| 243 | + </code> |
| 244 | + {/if} |
| 245 | + {#if activeCodeTab === 'SVG'} |
| 246 | + <button type="button" title="Copy SVG" data-copy-id="svg" class="m12 mb0 s-btn s-btn__sm s-btn__clear s-btn__icon" use:copyToClipboard={selectedVariant.svg}> |
| 247 | + {#if copied === 'svg'} |
| 248 | + <Icon src={IconCheckFillCircle} class="fc-green-400" /> Copied SVG! |
| 249 | + {:else} |
| 250 | + <Icon src={IconStackCards} /> Copy SVG |
| 251 | + {/if} |
| 252 | + </button> |
| 253 | +
|
| 254 | + <TextArea size="sm" class="m12 hs2 ff-mono" id="asset-svg-code" label="SVG" hideLabel readonly value={selectedVariant.svg} /> |
| 255 | + {/if} |
| 256 | + </div> |
| 257 | +
|
| 258 | + <div class="fs-caption px16 pb16 fc-black-400"> |
| 259 | + <b>Asset last updated:</b><br/> |
| 260 | + <time datetime={selectedVariant.updatedAt}> |
| 261 | + {new Date(selectedVariant.updatedAt).toLocaleDateString('en-US', { |
| 262 | + year: 'numeric', |
| 263 | + month: 'short', |
| 264 | + day: 'numeric', |
| 265 | + hour: 'numeric', |
| 266 | + minute: 'numeric', |
| 267 | + })} |
| 268 | + </time> |
| 269 | + </div> |
| 270 | + {/if} |
| 271 | +</aside> |
274 | 272 |
|
275 | 273 | <style> |
276 | 274 | .icons-grid { |
|
0 commit comments