refactor: reorganize component imports and enhance index page layout
- Grouped component imports into categories for better organization. - Updated the layout of the index page to include a gallery structure. - Added new sections for Button, Badge, Selection Controls, TextField, Select, Numeric Stepper, Avatar, Loading Bar, List Item, Link, Tabs, Breadcrumb, Pagination, Notification, Tooltip, Card, Navbar, Sidebar, Modal, and Icons. - Improved styling for better visual hierarchy and spacing. - Implemented a theme toggle feature with persistent state using localStorage.
This commit is contained in:
@@ -1,30 +1,28 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.link {
|
||||
.link__container {
|
||||
width: fit-content;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.link {
|
||||
text-decoration: none;
|
||||
color: var(--nds-primary);
|
||||
@include text-base;
|
||||
&:hover {
|
||||
color: var(--nds-text);
|
||||
opacity: 0.25;
|
||||
}
|
||||
&:active {
|
||||
color: var(--nds-text);
|
||||
opacity: 0.25;
|
||||
}
|
||||
&__container {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: var(--nds-border-width-medium) dashed var(--nds-secondary);
|
||||
&:hover {
|
||||
background-color: var(--nds-secondary);
|
||||
border-bottom: var(--nds-border-width-medium) dashed var(--nds-accent);
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--nds-primary);
|
||||
border-bottom: var(--nds-border-width-medium) dashed var(--nds-secondary);
|
||||
}
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--nds-spacing-3xs);
|
||||
border-bottom: 1px solid transparent;
|
||||
transition:
|
||||
border-color 130ms ease,
|
||||
color 130ms ease;
|
||||
&:hover {
|
||||
border-bottom-color: var(--nds-primary);
|
||||
}
|
||||
}
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--nds-ring);
|
||||
border-radius: var(--nds-radius-xs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,34 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.loading-bar {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
background-color: var(--nds-text);
|
||||
background-color: var(--nds-surface-2);
|
||||
overflow: hidden;
|
||||
border-radius: var(--nds-radius-sm);
|
||||
|
||||
border-radius: var(--nds-radius-full);
|
||||
&__progress {
|
||||
height: 100%;
|
||||
background-color: var(--nds-primary);
|
||||
transition: width 0.3s ease;
|
||||
border-radius: var(--nds-radius-sm);
|
||||
border-radius: var(--nds-radius-full);
|
||||
transition: width 0.35s ease;
|
||||
}
|
||||
|
||||
&__unknown {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -50%;
|
||||
width: 50%;
|
||||
left: 0;
|
||||
width: 40%;
|
||||
height: 100%;
|
||||
background-color: var(--nds-primary);
|
||||
border-radius: var(--nds-radius-sm);
|
||||
animation: loadingBarIndeterminate 1.5s infinite;
|
||||
border-radius: var(--nds-radius-full);
|
||||
animation: nds-lb 1.3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes loadingBarIndeterminate {
|
||||
from {
|
||||
left: -50%;
|
||||
}
|
||||
to {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
@keyframes nds-lb {
|
||||
0% {
|
||||
left: -40%;
|
||||
}
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
---
|
||||
export interface Props {
|
||||
type: 'known' | 'unknown';
|
||||
type: "known" | "unknown";
|
||||
percentage?: number;
|
||||
width?: string;
|
||||
width?: string;
|
||||
}
|
||||
const { type, percentage, width } = Astro.props;
|
||||
---
|
||||
<div class='loading-bar loading-bar--${type}' style={width ? `width: ${width}` : undefined}>
|
||||
{type === 'known' && percentage !== undefined ? (
|
||||
<div class='loading-bar__progress' style={`width: ${percentage}%`}></div>
|
||||
) : (
|
||||
<div class='loading-bar__unknown'></div>
|
||||
)}
|
||||
|
||||
<div
|
||||
class={`loading-bar loading-bar--${type}`}
|
||||
style={width ? `width: ${width}` : undefined}
|
||||
>
|
||||
{
|
||||
type === "known" && percentage !== undefined ? (
|
||||
<div class="loading-bar__progress" style={`width: ${percentage}%`} />
|
||||
) : (
|
||||
<div class="loading-bar__unknown" />
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use './loadingBar';
|
||||
</style>
|
||||
@use "./_loadingBar.scss";
|
||||
</style>
|
||||
|
||||
@@ -1,61 +1,50 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.notification {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: var(--nds-spacing-sm) var(--nds-spacing-xs) ;
|
||||
border-radius: var(--nds-radius-md);
|
||||
@include text-sm;
|
||||
&__error {
|
||||
background-color: var(--nds-error-low);
|
||||
&__close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--nds-error-medium);
|
||||
cursor: pointer;
|
||||
}
|
||||
&__content {
|
||||
color: var(--nds-error-high);
|
||||
}
|
||||
}
|
||||
|
||||
&__success {
|
||||
background-color: var(--nds-success-low);
|
||||
&__close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--nds-success-medium);
|
||||
cursor: pointer;
|
||||
}
|
||||
&__content {
|
||||
color: var(--nds-success-high);
|
||||
}
|
||||
}
|
||||
|
||||
&__warning {
|
||||
background-color: var(--nds-warning-low);
|
||||
&__close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--nds-warning-medium);
|
||||
cursor: pointer;
|
||||
}
|
||||
&__content {
|
||||
color: var(--nds-warning-high);
|
||||
}
|
||||
}
|
||||
|
||||
gap: var(--nds-spacing-sm);
|
||||
padding: var(--nds-spacing-sm) var(--nds-spacing-md);
|
||||
border-radius: var(--nds-radius-lg);
|
||||
background-color: var(--nds-surface);
|
||||
box-shadow: var(--nds-shadow-md);
|
||||
border-left: 3px solid var(--nds-info-medium);
|
||||
@include text-base;
|
||||
max-width: 400px;
|
||||
&__info {
|
||||
background-color: var(--nds-info-low);
|
||||
&__close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--nds-info-medium);
|
||||
cursor: pointer;
|
||||
}
|
||||
&__content {
|
||||
color: var(--nds-info-high);
|
||||
border-left-color: var(--nds-info-medium);
|
||||
}
|
||||
&__success {
|
||||
border-left-color: var(--nds-success-medium);
|
||||
}
|
||||
&__warning {
|
||||
border-left-color: var(--nds-warning-medium);
|
||||
}
|
||||
&__error {
|
||||
border-left-color: var(--nds-error-medium);
|
||||
}
|
||||
&__info__content,
|
||||
&__success__content,
|
||||
&__warning__content,
|
||||
&__error__content {
|
||||
color: var(--nds-text);
|
||||
flex: 1;
|
||||
}
|
||||
&__info__close,
|
||||
&__success__close,
|
||||
&__warning__close,
|
||||
&__error__close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
color: var(--nds-neutral);
|
||||
padding: 0;
|
||||
border-radius: var(--nds-radius-sm);
|
||||
transition: color 120ms ease;
|
||||
&:hover {
|
||||
color: var(--nds-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
---
|
||||
import { CloseIcon } from "../Icons";
|
||||
|
||||
|
||||
export interface Props {
|
||||
type: 'info' | 'success' | 'warning' | 'error';
|
||||
type: "info" | "success" | "warning" | "error";
|
||||
}
|
||||
const notificationUUID = `notification-${Math.random().toString(36).substr(2, 9)}`;
|
||||
const notificationUUID = `notification-${Math.random().toString(36).slice(2, 11)}`;
|
||||
const { type } = Astro.props;
|
||||
---
|
||||
|
||||
<div class={`notification notification__${type}`} role="alert" id={notificationUUID}>
|
||||
<div class=`notification__${type}__content`>
|
||||
<div
|
||||
class={`notification notification__${type}`}
|
||||
role="alert"
|
||||
id={notificationUUID}
|
||||
>
|
||||
<div class={`notification__${type}__content`}>
|
||||
<slot />
|
||||
</div>
|
||||
<button class={`notification__${type}__close`} aria-label="Close notification" onclick={`document.getElementById('${notificationUUID}')?.remove()`}>
|
||||
<button
|
||||
class={`notification__${type}__close`}
|
||||
aria-label="Close notification"
|
||||
onclick={`document.getElementById('${notificationUUID}')?.remove()`}
|
||||
>
|
||||
<CloseIcon size={16} label="Close notification" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use './_notification.scss';
|
||||
</style>
|
||||
@use "./_notification.scss";
|
||||
</style>
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--nds-spacing-xs);
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: fit-content;
|
||||
cursor: pointer;
|
||||
padding: var(--nds-spacing-2xs);
|
||||
@include text-base;
|
||||
|
||||
&--active {
|
||||
color: var(--nds-primary);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 120%;
|
||||
height: 1px;
|
||||
background-color: var(--nds-primary);
|
||||
border-radius: var(--nds-radius-sm);
|
||||
}
|
||||
}
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: var(--nds-spacing-2xs);
|
||||
border-bottom: 1px solid var(--nds-border);
|
||||
width: fit-content;
|
||||
&__item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--nds-spacing-2xs);
|
||||
padding: var(--nds-spacing-xs) var(--nds-spacing-sm);
|
||||
cursor: pointer;
|
||||
@include text-label;
|
||||
color: var(--nds-neutral);
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
transition:
|
||||
color 130ms ease,
|
||||
border-color 130ms ease;
|
||||
&:hover {
|
||||
color: var(--nds-text);
|
||||
}
|
||||
}
|
||||
&--active {
|
||||
color: var(--nds-text);
|
||||
border-bottom-color: var(--nds-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab__content {
|
||||
padding-top: var(--nds-spacing-md);
|
||||
@include text-base;
|
||||
color: var(--nds-text);
|
||||
&[hidden] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,13 @@
|
||||
.toggle {
|
||||
background-color: var(--nds-disabled);
|
||||
border-radius: var(--nds-radius-full);
|
||||
padding: var(--nds-spacing-2xs);
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: left;
|
||||
cursor: pointer;
|
||||
transition: background-color 160ms ease;
|
||||
position: relative;
|
||||
&-switch {
|
||||
color: var(--nds-text);
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background-color: var(--nds-text);
|
||||
border-radius: var(--nds-radius-full);
|
||||
position: absolute;
|
||||
left: var(--nds-spacing-2xs);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
transition: left 160ms ease, background-color 160ms ease, transform 160ms ease;
|
||||
}
|
||||
&-active {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
background-color: var(--nds-primary);
|
||||
.toggle-switch {
|
||||
left: calc(100% - var(--nds-spacing-2xs) - 15px);
|
||||
}
|
||||
}
|
||||
--w: 44px; --h: 24px; --pad: 3px;
|
||||
position: relative; width: var(--w); height: var(--h);
|
||||
background-color: var(--nds-disabled); border-radius: var(--nds-radius-full);
|
||||
padding: var(--pad); display: flex; align-items: center; cursor: pointer;
|
||||
transition: background-color 180ms ease;
|
||||
&-switch { width: calc(var(--h) - var(--pad) * 2); height: calc(var(--h) - var(--pad) * 2);
|
||||
background-color: #fff; border-radius: var(--nds-radius-full); box-shadow: var(--nds-shadow-sm);
|
||||
transition: transform 180ms cubic-bezier(.34,1.4,.6,1); }
|
||||
&-active { background-color: var(--nds-primary); }
|
||||
&-active .toggle-switch { transform: translateX(calc(var(--w) - var(--h))); }
|
||||
}
|
||||
toggle-switch:focus-visible .toggle { box-shadow: 0 0 0 3px var(--nds-ring); outline: none; }
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
import { boolean } from 'astro:schema';
|
||||
|
||||
export interface Props {
|
||||
'data-checked': boolean;
|
||||
'data-checked'?: boolean | string;
|
||||
name?: string;
|
||||
id: string;
|
||||
}
|
||||
@@ -10,7 +8,7 @@ export interface Props {
|
||||
const { 'data-checked': dataChecked = 'false', name = 'toggle', id } = Astro.props;
|
||||
---
|
||||
|
||||
<toggle-switch data-checked={dataChecked} data-name={name} id={id}>
|
||||
<toggle-switch data-checked={String(dataChecked)} data-name={name} id={id}>
|
||||
<div class="toggle">
|
||||
<div class="toggle-switch"></div>
|
||||
</div>
|
||||
@@ -35,7 +33,7 @@ const { 'data-checked': dataChecked = 'false', name = 'toggle', id } = Astro.pro
|
||||
|
||||
this.dispatchEvent(new CustomEvent('change', {
|
||||
detail: { checked: this._checked, name: this.dataset.name },
|
||||
bubbles: true,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
}
|
||||
@@ -59,4 +57,4 @@ const { 'data-checked': dataChecked = 'false', name = 'toggle', id } = Astro.pro
|
||||
|
||||
<style lang="scss">
|
||||
@use './_toggle.scss';
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
gap: var(--nds-spacing-sm);
|
||||
}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--nds-spacing-2xs);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.pagination-number {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
padding: 0 var(--nds-spacing-2xs);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--nds-radius-full);
|
||||
border-radius: var(--nds-radius-md);
|
||||
cursor: pointer;
|
||||
@include text-label;
|
||||
color: var(--nds-text);
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
transition: all 120ms ease;
|
||||
user-select: none;
|
||||
&:hover:not(.pagination-number__disabled):not(.pagination-number__selected) {
|
||||
background-color: var(--nds-secondary);
|
||||
cursor: pointer;
|
||||
}
|
||||
&:active:not(.pagination-number__disabled):not(.pagination-number__selected) {
|
||||
background-color: var(--nds-accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
&__disabled {
|
||||
background-color: var(--nds-disabled);
|
||||
cursor: not-allowed;
|
||||
border-color: var(--nds-border-strong);
|
||||
background-color: var(--nds-surface-hover);
|
||||
}
|
||||
&__selected {
|
||||
background-color: var(--nds-primary);
|
||||
cursor: pointer;
|
||||
color: var(--nds-on-primary);
|
||||
}
|
||||
}
|
||||
&__disabled {
|
||||
color: var(--nds-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
min-height: 84px;
|
||||
padding: var(--nds-spacing-sm);
|
||||
resize: vertical;
|
||||
width: 100% !important;
|
||||
line-height: 1.5;
|
||||
}
|
||||
&__charCount {
|
||||
|
||||
Reference in New Issue
Block a user