@bigtablet/design-system 1.1.3 → 1.2.2

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/dist/index.js CHANGED
@@ -1,12 +1,612 @@
1
- import { jsx } from 'react/jsx-runtime';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import * as React4 from 'react';
3
+ import { createContext } from 'react';
4
+ import 'react-dom';
5
+ import { ToastContainer, Slide, toast } from 'react-toastify';
6
+ import 'react-toastify/dist/ReactToastify.css';
7
+ import ReactMarkdown from 'react-markdown';
8
+ import remarkGfm from 'remark-gfm';
9
+ import { ChevronDown, Check } from 'lucide-react';
2
10
 
3
11
  // src/ui/display/card/index.tsx
4
- var Card = ({ shadow = "sm", padding = "md", bordered, className, ...props }) => {
5
- const cls = ["card", `card--shadow-${shadow}`, `card--p-${padding}`, bordered && "card--bordered", className].filter(Boolean).join(" ");
12
+ var Card = ({
13
+ shadow = "sm",
14
+ padding = "md",
15
+ bordered,
16
+ className,
17
+ ...props
18
+ }) => {
19
+ const cls = [
20
+ "card",
21
+ `card--shadow-${shadow}`,
22
+ `card--p-${padding}`,
23
+ bordered && "card--bordered",
24
+ className
25
+ ].filter(Boolean).join(" ");
6
26
  return /* @__PURE__ */ jsx("div", { className: cls, ...props });
7
27
  };
28
+ createContext(null);
29
+ var Alert = ({
30
+ variant = "info",
31
+ title,
32
+ icon,
33
+ closable,
34
+ onClose,
35
+ showActions = false,
36
+ onConfirm,
37
+ onCancel,
38
+ confirmText = "\uD655\uC778",
39
+ cancelText = "\uCDE8\uC18C",
40
+ actionsAlign = "left",
41
+ className,
42
+ children,
43
+ ...props
44
+ }) => {
45
+ return /* @__PURE__ */ jsxs(
46
+ "div",
47
+ {
48
+ className: ["alert", `alert--${variant}`, closable && "alert--closable", className].filter(Boolean).join(" "),
49
+ role: "alert",
50
+ "aria-live": "polite",
51
+ ...props,
52
+ children: [
53
+ icon && /* @__PURE__ */ jsx("span", { className: "alert__icon", "aria-hidden": "true", children: icon }),
54
+ /* @__PURE__ */ jsxs("div", { className: "alert__content", children: [
55
+ title && /* @__PURE__ */ jsx("div", { className: "alert__title", children: title }),
56
+ children && /* @__PURE__ */ jsx("div", { className: "alert__desc", children }),
57
+ showActions && /* @__PURE__ */ jsxs("div", { className: `alert__actions alert__actions--${actionsAlign}`, children: [
58
+ onCancel && /* @__PURE__ */ jsx(
59
+ "button",
60
+ {
61
+ type: "button",
62
+ className: "alert__button alert__button--cancel",
63
+ onClick: onCancel,
64
+ children: cancelText
65
+ }
66
+ ),
67
+ onConfirm && /* @__PURE__ */ jsx(
68
+ "button",
69
+ {
70
+ type: "button",
71
+ className: "alert__button alert__button--confirm",
72
+ onClick: onConfirm,
73
+ children: confirmText
74
+ }
75
+ )
76
+ ] })
77
+ ] }),
78
+ closable && /* @__PURE__ */ jsx(
79
+ "button",
80
+ {
81
+ type: "button",
82
+ className: "alert__close",
83
+ "aria-label": "\uB2EB\uAE30",
84
+ onClick: onClose,
85
+ children: /* @__PURE__ */ jsxs(
86
+ "svg",
87
+ {
88
+ width: "16",
89
+ height: "16",
90
+ viewBox: "0 0 24 24",
91
+ fill: "none",
92
+ stroke: "currentColor",
93
+ strokeWidth: "2",
94
+ strokeLinecap: "round",
95
+ strokeLinejoin: "round",
96
+ children: [
97
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
98
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
99
+ ]
100
+ }
101
+ )
102
+ }
103
+ )
104
+ ]
105
+ }
106
+ );
107
+ };
8
108
  var Loading = ({ size = 24 }) => {
9
- return /* @__PURE__ */ jsx("span", { className: "loading", style: { width: size, height: size }, "aria-label": "Loading" });
109
+ return /* @__PURE__ */ jsx(
110
+ "span",
111
+ {
112
+ className: "loading",
113
+ style: { width: size, height: size },
114
+ "aria-label": "Loading"
115
+ }
116
+ );
117
+ };
118
+ var ToastProvider = () => /* @__PURE__ */ jsx(
119
+ ToastContainer,
120
+ {
121
+ position: "top-right",
122
+ autoClose: 2e3,
123
+ hideProgressBar: false,
124
+ newestOnTop: false,
125
+ closeOnClick: true,
126
+ rtl: false,
127
+ pauseOnFocusLoss: true,
128
+ draggable: true,
129
+ pauseOnHover: true,
130
+ theme: "light",
131
+ transition: Slide
132
+ }
133
+ );
134
+ var useToast = () => {
135
+ return {
136
+ success: (msg) => toast.success(msg),
137
+ error: (msg) => toast.error(msg),
138
+ warning: (msg) => toast.warning(msg),
139
+ info: (msg) => toast.info(msg),
140
+ message: (msg) => toast(msg)
141
+ };
142
+ };
143
+ var Button = ({
144
+ variant = "primary",
145
+ size = "md",
146
+ className,
147
+ style,
148
+ ...props
149
+ }) => {
150
+ const classes = ["btn", `btn--${variant}`, `btn--${size}`, className].filter(Boolean).join(" ");
151
+ return /* @__PURE__ */ jsx("button", { className: classes, ...props });
152
+ };
153
+ var Checkbox = ({
154
+ label,
155
+ size = "md",
156
+ indeterminate,
157
+ className,
158
+ ...props
159
+ }) => {
160
+ const ref = React4.useRef(null);
161
+ React4.useEffect(() => {
162
+ if (ref.current) ref.current.indeterminate = !!indeterminate;
163
+ }, [indeterminate]);
164
+ return /* @__PURE__ */ jsxs(
165
+ "label",
166
+ {
167
+ className: ["checkbox", `checkbox--${size}`, className].filter(Boolean).join(" "),
168
+ children: [
169
+ /* @__PURE__ */ jsx("input", { ref, type: "checkbox", className: "checkbox__input", ...props }),
170
+ /* @__PURE__ */ jsx("span", { className: "checkbox__box", "aria-hidden": true }),
171
+ label && /* @__PURE__ */ jsx("span", { className: "checkbox__label", children: label })
172
+ ]
173
+ }
174
+ );
175
+ };
176
+ var FileInput = ({
177
+ label = "Choose file",
178
+ onFiles,
179
+ className,
180
+ ...props
181
+ }) => {
182
+ const id = React4.useId();
183
+ return /* @__PURE__ */ jsxs("div", { className: ["file", className].filter(Boolean).join(" "), children: [
184
+ /* @__PURE__ */ jsx(
185
+ "input",
186
+ {
187
+ id,
188
+ type: "file",
189
+ className: "file__input",
190
+ onChange: (e) => onFiles?.(e.currentTarget.files),
191
+ ...props
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsx("label", { htmlFor: id, className: "file__label", children: label })
195
+ ] });
196
+ };
197
+ var MarkdownEditor = ({
198
+ label,
199
+ placeholder,
200
+ value,
201
+ onChangeAction,
202
+ rows = 14
203
+ }) => {
204
+ const id = React4.useId();
205
+ return /* @__PURE__ */ jsxs("div", { className: "md", children: [
206
+ label && /* @__PURE__ */ jsx("label", { className: "md__label", htmlFor: id, children: label }),
207
+ /* @__PURE__ */ jsxs("div", { className: "md__grid", children: [
208
+ /* @__PURE__ */ jsx(
209
+ "textarea",
210
+ {
211
+ id,
212
+ className: "md__input",
213
+ rows,
214
+ value,
215
+ placeholder,
216
+ onChange: (e) => onChangeAction(e.target.value)
217
+ }
218
+ ),
219
+ /* @__PURE__ */ jsx("div", { className: "md__preview markdown-body", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: value || "\uBBF8\uB9AC\uBCF4\uAE30 \uC601\uC5ED\uC785\uB2C8\uB2E4. \uB9C8\uD06C\uB2E4\uC6B4\uC744 \uC785\uB825\uD558\uC138\uC694." }) })
220
+ ] })
221
+ ] });
222
+ };
223
+ var Radio = ({
224
+ label,
225
+ size = "md",
226
+ className,
227
+ ...props
228
+ }) => {
229
+ return /* @__PURE__ */ jsxs(
230
+ "label",
231
+ {
232
+ className: ["radio", `radio--${size}`, className].filter(Boolean).join(" "),
233
+ children: [
234
+ /* @__PURE__ */ jsx("input", { type: "radio", className: "radio__input", ...props }),
235
+ /* @__PURE__ */ jsx("span", { className: "radio__dot", "aria-hidden": true }),
236
+ label && /* @__PURE__ */ jsx("span", { className: "radio__label", children: label })
237
+ ]
238
+ }
239
+ );
240
+ };
241
+ function Select({
242
+ id,
243
+ label,
244
+ placeholder = "Select\u2026",
245
+ options,
246
+ value,
247
+ onChange,
248
+ defaultValue = null,
249
+ disabled,
250
+ size = "md",
251
+ variant = "outline",
252
+ fullWidth,
253
+ className
254
+ }) {
255
+ const internalId = React4.useId();
256
+ const selectId = id ?? internalId;
257
+ const isControlled = value !== void 0;
258
+ const [internal, setInternal] = React4.useState(defaultValue);
259
+ const currentValue = isControlled ? value ?? null : internal;
260
+ const [open, setOpen] = React4.useState(false);
261
+ const [activeIndex, setActiveIndex] = React4.useState(-1);
262
+ const wrapperRef = React4.useRef(null);
263
+ const listRef = React4.useRef(null);
264
+ const currentOption = React4.useMemo(
265
+ () => options.find((o) => o.value === currentValue) ?? null,
266
+ [options, currentValue]
267
+ );
268
+ const setValue = React4.useCallback(
269
+ (next) => {
270
+ const opt = options.find((o) => o.value === next) ?? null;
271
+ if (!isControlled) setInternal(next);
272
+ onChange?.(next, opt);
273
+ },
274
+ [isControlled, onChange, options]
275
+ );
276
+ React4.useEffect(() => {
277
+ const onDocClick = (e) => {
278
+ if (!wrapperRef.current) return;
279
+ if (!wrapperRef.current.contains(e.target)) setOpen(false);
280
+ };
281
+ document.addEventListener("mousedown", onDocClick);
282
+ return () => document.removeEventListener("mousedown", onDocClick);
283
+ }, []);
284
+ const moveActive = (dir) => {
285
+ if (!open) {
286
+ setOpen(true);
287
+ return;
288
+ }
289
+ let i = activeIndex;
290
+ const len = options.length;
291
+ for (let step = 0; step < len; step++) {
292
+ i = (i + dir + len) % len;
293
+ if (!options[i].disabled) {
294
+ setActiveIndex(i);
295
+ break;
296
+ }
297
+ }
298
+ };
299
+ const commitActive = () => {
300
+ if (activeIndex < 0 || activeIndex >= options.length) return;
301
+ const opt = options[activeIndex];
302
+ if (!opt.disabled) {
303
+ setValue(opt.value);
304
+ setOpen(false);
305
+ }
306
+ };
307
+ const onKeyDown = (e) => {
308
+ if (disabled) return;
309
+ switch (e.key) {
310
+ case " ":
311
+ case "Enter":
312
+ e.preventDefault();
313
+ if (!open) setOpen(true);
314
+ else commitActive();
315
+ break;
316
+ case "ArrowDown":
317
+ e.preventDefault();
318
+ moveActive(1);
319
+ break;
320
+ case "ArrowUp":
321
+ e.preventDefault();
322
+ moveActive(-1);
323
+ break;
324
+ case "Home":
325
+ e.preventDefault();
326
+ setOpen(true);
327
+ setActiveIndex(options.findIndex((o) => !o.disabled));
328
+ break;
329
+ case "End":
330
+ e.preventDefault();
331
+ setOpen(true);
332
+ for (let i = options.length - 1; i >= 0; i--) {
333
+ if (!options[i].disabled) {
334
+ setActiveIndex(i);
335
+ break;
336
+ }
337
+ }
338
+ break;
339
+ case "Escape":
340
+ e.preventDefault();
341
+ setOpen(false);
342
+ break;
343
+ }
344
+ };
345
+ React4.useEffect(() => {
346
+ if (open) {
347
+ const idx = Math.max(
348
+ 0,
349
+ options.findIndex((o) => o.value === currentValue && !o.disabled)
350
+ );
351
+ setActiveIndex(idx === -1 ? 0 : idx);
352
+ }
353
+ }, [open, options, currentValue]);
354
+ return /* @__PURE__ */ jsxs(
355
+ "div",
356
+ {
357
+ ref: wrapperRef,
358
+ className: `select${className ? ` ${className}` : ""}`,
359
+ style: fullWidth ? { width: "100%" } : void 0,
360
+ children: [
361
+ label && /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "select__label", children: label }),
362
+ /* @__PURE__ */ jsxs(
363
+ "button",
364
+ {
365
+ id: selectId,
366
+ type: "button",
367
+ className: [
368
+ "select__control",
369
+ `select__control--${variant}`,
370
+ `select__control--${size}`,
371
+ open && "is-open",
372
+ disabled && "is-disabled"
373
+ ].filter(Boolean).join(" "),
374
+ "aria-haspopup": "listbox",
375
+ "aria-expanded": open,
376
+ "aria-controls": `${selectId}-listbox`,
377
+ onClick: () => !disabled && setOpen((o) => !o),
378
+ onKeyDown,
379
+ disabled,
380
+ children: [
381
+ /* @__PURE__ */ jsx(
382
+ "span",
383
+ {
384
+ className: currentOption ? "select__value" : "select__placeholder",
385
+ children: currentOption ? currentOption.label : placeholder
386
+ }
387
+ ),
388
+ /* @__PURE__ */ jsx("span", { className: "select__icon", "aria-hidden": true, children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
389
+ ]
390
+ }
391
+ ),
392
+ open && /* @__PURE__ */ jsx(
393
+ "ul",
394
+ {
395
+ ref: listRef,
396
+ id: `${selectId}-listbox`,
397
+ role: "listbox",
398
+ className: "select__list",
399
+ children: options.map((opt, i) => {
400
+ const selected = currentValue === opt.value;
401
+ const active = i === activeIndex;
402
+ return /* @__PURE__ */ jsxs(
403
+ "li",
404
+ {
405
+ role: "option",
406
+ "aria-selected": selected,
407
+ className: [
408
+ "select__option",
409
+ selected && "is-selected",
410
+ active && "is-active",
411
+ opt.disabled && "is-disabled"
412
+ ].filter(Boolean).join(" "),
413
+ onMouseEnter: () => !opt.disabled && setActiveIndex(i),
414
+ onClick: () => {
415
+ if (opt.disabled) return;
416
+ setValue(opt.value);
417
+ setOpen(false);
418
+ },
419
+ children: [
420
+ /* @__PURE__ */ jsx("span", { children: opt.label }),
421
+ selected && /* @__PURE__ */ jsx(Check, { size: 16, "aria-hidden": true })
422
+ ]
423
+ },
424
+ opt.value
425
+ );
426
+ })
427
+ }
428
+ )
429
+ ]
430
+ }
431
+ );
432
+ }
433
+ var Switch = ({
434
+ checked,
435
+ defaultChecked,
436
+ onChange,
437
+ size = "md",
438
+ disabled,
439
+ className,
440
+ ...props
441
+ }) => {
442
+ const controlled = checked !== void 0;
443
+ const [inner, setInner] = React4.useState(!!defaultChecked);
444
+ const on = controlled ? !!checked : inner;
445
+ const toggle = () => {
446
+ if (disabled) return;
447
+ const next = !on;
448
+ if (!controlled) setInner(next);
449
+ onChange?.(next);
450
+ };
451
+ return /* @__PURE__ */ jsx(
452
+ "button",
453
+ {
454
+ type: "button",
455
+ role: "switch",
456
+ "aria-checked": on,
457
+ disabled,
458
+ onClick: toggle,
459
+ className: [
460
+ "switch",
461
+ `switch--${size}`,
462
+ on && "is-on",
463
+ disabled && "is-disabled",
464
+ className
465
+ ].filter(Boolean).join(" "),
466
+ ...props,
467
+ children: /* @__PURE__ */ jsx("span", { className: "switch__thumb" })
468
+ }
469
+ );
470
+ };
471
+ var TextField = React4.forwardRef(
472
+ ({
473
+ id,
474
+ label,
475
+ helperText,
476
+ error,
477
+ success,
478
+ variant = "outline",
479
+ size = "md",
480
+ leftIcon,
481
+ rightIcon,
482
+ fullWidth,
483
+ className,
484
+ onChangeAction,
485
+ ...props
486
+ }, ref) => {
487
+ const inputId = id ?? React4.useId();
488
+ const helperId = helperText ? `${inputId}-help` : void 0;
489
+ const classNames = [
490
+ "tf__input",
491
+ `tf__input--${variant}`,
492
+ `tf__input--${size}`,
493
+ leftIcon && "tf__input--with-left",
494
+ rightIcon && "tf__input--with-right",
495
+ error && "tf__input--error",
496
+ success && "tf__input--success",
497
+ className
498
+ ].filter(Boolean).join(" ");
499
+ return /* @__PURE__ */ jsxs("div", { className: "tf", style: fullWidth ? { width: "100%" } : void 0, children: [
500
+ label && /* @__PURE__ */ jsx("label", { className: "tf__label", htmlFor: inputId, children: label }),
501
+ /* @__PURE__ */ jsxs("div", { className: "tf__wrapper", children: [
502
+ leftIcon && /* @__PURE__ */ jsx("span", { className: "tf__icon tf__icon--left", children: leftIcon }),
503
+ /* @__PURE__ */ jsx(
504
+ "input",
505
+ {
506
+ id: inputId,
507
+ ref,
508
+ className: classNames,
509
+ "aria-invalid": !!error,
510
+ "aria-describedby": helperId,
511
+ ...props,
512
+ onChange: onChangeAction
513
+ }
514
+ ),
515
+ rightIcon && /* @__PURE__ */ jsx("span", { className: "tf__icon tf__icon--right", children: rightIcon })
516
+ ] }),
517
+ helperText && /* @__PURE__ */ jsx(
518
+ "div",
519
+ {
520
+ id: helperId,
521
+ className: `tf__helper ${error ? "tf__helper--error" : ""}`,
522
+ children: helperText
523
+ }
524
+ )
525
+ ] });
526
+ }
527
+ );
528
+ TextField.displayName = "TextField";
529
+ var Pagination = ({ page, hasNext, onChange }) => {
530
+ const prevDisabled = page <= 1;
531
+ const nextDisabled = !hasNext;
532
+ return /* @__PURE__ */ jsxs("nav", { className: "pagination", "aria-label": "Pagination", children: [
533
+ /* @__PURE__ */ jsx(
534
+ "button",
535
+ {
536
+ className: "pagination__item",
537
+ onClick: () => !prevDisabled && onChange(page - 1),
538
+ disabled: prevDisabled,
539
+ children: "Prev"
540
+ }
541
+ ),
542
+ /* @__PURE__ */ jsx("span", { className: "pagination__page", children: page }),
543
+ /* @__PURE__ */ jsx(
544
+ "button",
545
+ {
546
+ className: "pagination__item",
547
+ onClick: () => !nextDisabled && onChange(page + 1),
548
+ disabled: nextDisabled,
549
+ children: "Next"
550
+ }
551
+ )
552
+ ] });
553
+ };
554
+ var Modal = ({
555
+ open,
556
+ onClose,
557
+ closeOnOverlay = true,
558
+ width = 520,
559
+ title,
560
+ children,
561
+ ...props
562
+ }) => {
563
+ React4.useEffect(() => {
564
+ const onKey = (e) => e.key === "Escape" && onClose?.();
565
+ if (open) document.addEventListener("keydown", onKey);
566
+ return () => document.removeEventListener("keydown", onKey);
567
+ }, [open, onClose]);
568
+ if (!open) return null;
569
+ return /* @__PURE__ */ jsx(
570
+ "div",
571
+ {
572
+ className: "modal",
573
+ role: "dialog",
574
+ "aria-modal": "true",
575
+ onClick: () => closeOnOverlay && onClose?.(),
576
+ children: /* @__PURE__ */ jsxs(
577
+ "div",
578
+ {
579
+ className: "modal__panel",
580
+ style: { width },
581
+ onClick: (e) => e.stopPropagation(),
582
+ ...props,
583
+ children: [
584
+ title && /* @__PURE__ */ jsx("div", { className: "modal__header", children: title }),
585
+ /* @__PURE__ */ jsx("div", { className: "modal__body", children })
586
+ ]
587
+ }
588
+ )
589
+ }
590
+ );
10
591
  };
592
+ var SkeletonCard = () => /* @__PURE__ */ jsxs("div", { className: "card-skeleton", children: [
593
+ /* @__PURE__ */ jsx("div", { className: "card-skeleton__thumb" }),
594
+ /* @__PURE__ */ jsxs("div", { className: "card-skeleton__text", children: [
595
+ /* @__PURE__ */ jsx("div", { className: "card-skeleton__line short" }),
596
+ /* @__PURE__ */ jsx("div", { className: "card-skeleton__line" })
597
+ ] })
598
+ ] });
599
+ var card_default = SkeletonCard;
600
+ var SkeletonList = () => /* @__PURE__ */ jsxs("div", { className: "request-item skeleton", children: [
601
+ /* @__PURE__ */ jsxs("div", { className: "request-item__left", children: [
602
+ /* @__PURE__ */ jsx("div", { className: "skeleton__title" }),
603
+ /* @__PURE__ */ jsxs("div", { className: "request-item__tags", children: [
604
+ /* @__PURE__ */ jsx("span", { className: "skeleton__tag" }),
605
+ /* @__PURE__ */ jsx("span", { className: "skeleton__tag" }),
606
+ /* @__PURE__ */ jsx("span", { className: "skeleton__tag" })
607
+ ] })
608
+ ] }),
609
+ /* @__PURE__ */ jsx("div", { className: "request-item__dday", children: /* @__PURE__ */ jsx("span", { className: "skeleton__dday" }) })
610
+ ] });
11
611
 
12
- export { Card, Loading };
612
+ export { Alert, Button, Card, Checkbox, FileInput, Loading, MarkdownEditor, Modal, Pagination, Radio, Select, card_default as SkeletonCard, SkeletonList, Switch, TextField, ToastProvider, useToast };
package/dist/next.css ADDED
@@ -0,0 +1,87 @@
1
+ /* src/ui/navigation/sidebar/style.scss */
2
+ .sidebar {
3
+ display: flex;
4
+ flex-direction: column;
5
+ height: 100%;
6
+ background: #ffffff;
7
+ border-right: 1px solid #e5e5e5;
8
+ padding: 0.5rem;
9
+ gap: 0.5rem;
10
+ }
11
+ .sidebar__brand {
12
+ padding: 0.5rem 0.5rem;
13
+ margin-bottom: 0.5rem;
14
+ border-bottom: 1px solid #e5e5e5;
15
+ }
16
+ .sidebar__brand-link {
17
+ display: block;
18
+ width: 100%;
19
+ }
20
+ .sidebar__brand-img {
21
+ display: block;
22
+ width: 100%;
23
+ height: auto;
24
+ object-fit: contain;
25
+ }
26
+ .sidebar__nav {
27
+ display: grid;
28
+ gap: 0.25rem;
29
+ padding-top: 0.5rem;
30
+ padding-bottom: 0.5rem;
31
+ }
32
+ .sidebar__item {
33
+ display: grid;
34
+ grid-template-columns: 24px 1fr;
35
+ align-items: center;
36
+ gap: 0.5rem;
37
+ padding: 0.5rem 0.75rem;
38
+ border-radius: 8px;
39
+ color: #3B3B3B;
40
+ background: transparent;
41
+ border: 1px solid transparent;
42
+ font-size: 0.9375rem;
43
+ line-height: 1.5;
44
+ cursor: pointer;
45
+ transition:
46
+ background-color 0.2s ease-out,
47
+ color 0.2s ease-out,
48
+ border-color 0.2s ease-out;
49
+ }
50
+ .sidebar__item:hover {
51
+ background: #fafafa;
52
+ color: #1F2937;
53
+ }
54
+ .sidebar__item:hover .sidebar__icon {
55
+ color: #1F2937;
56
+ }
57
+ .sidebar__item.is-active {
58
+ position: relative;
59
+ background: #ffffff;
60
+ border-color: #e5e5e5;
61
+ color: #1F2937;
62
+ box-shadow: inset 0 0 0 1px #e5e5e5;
63
+ }
64
+ .sidebar__item.is-active::before {
65
+ content: "";
66
+ position: absolute;
67
+ left: 0;
68
+ top: 6px;
69
+ bottom: 6px;
70
+ width: 3px;
71
+ border-radius: 9999px;
72
+ background: #000000;
73
+ }
74
+ .sidebar__item.is-active .sidebar__icon {
75
+ color: #1F2937;
76
+ }
77
+ .sidebar__icon {
78
+ display: inline-grid;
79
+ place-items: center;
80
+ color: #6B7280;
81
+ transition: color 0.2s ease-out;
82
+ }
83
+ .sidebar__label {
84
+ white-space: nowrap;
85
+ overflow: hidden;
86
+ text-overflow: ellipsis;
87
+ }