diff --git a/package.json b/package.json index 40e879b..537a1a1 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ }, "devDependencies": { "@chromatic-com/storybook": "1", - "@floating-ui/react": "^0.26.15", + "@floating-ui/react": "^0.26.16", "@ianvs/prettier-plugin-sort-imports": "^4.2.1", "@material/material-color-utilities": "^0.2.7", "@mdi/js": "^7.4.47", @@ -34,10 +34,10 @@ "@storybook/react-vite": "^8.1.1", "@types/react": "^18.3.2", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "@vitejs/plugin-react": "^4.2.1", - "chromatic": "^11.3.2", + "chromatic": "^11.3.5", "clsx": "^2.1.1", "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.2", @@ -45,7 +45,7 @@ "eslint-plugin-storybook": "^0.8.0", "glob": "^10.3.15", "prettier": "^3.2.5", - "sass": "^1.77.1", + "sass": "^1.77.2", "storybook": "^8.1.1", "styled-jsx": "^5.1.3", "typescript": "^5.4.5", diff --git a/src/components/tabs/Tabs.stories.tsx b/src/components/tabs/Tabs.stories.tsx index ec35855..ca1c071 100644 --- a/src/components/tabs/Tabs.stories.tsx +++ b/src/components/tabs/Tabs.stories.tsx @@ -94,10 +94,38 @@ export const Scrolling: Story = { ], args: { items: [ - 1, 666666, 8080, 3, 443, 8888, 1, 666666, 8080, 3, 443, 8888, + 20, 21, 22, 23, 25, 53, 67, 68, 69, 80, 110, 119, 123, 137, 138, + 139, 143, 161, 162, 179, 194, 443, 465, 514, 515, 587, 636, 993, + 995, 1080, 1194, 1433, 1434, 1521, 1723, 1812, 1813, 2049, 3306, + 3389, 5060, 5061, 5432, 5900, 6379, 8080, 8443, 27017, 27018, 27019, + 27020, 50000, ].map((i, value) => ({ label: `Tab ${i}`, value: String(value), })), }, } + +export const Block: Story = { + args: { + variant: 'block', + defaultValue: 'Tab 1', + items: [ + { + value: 'Tab 1', + icon: , + direction: 'row', + }, + { + value: 'Tab 2', + icon: , + direction: 'row', + }, + { + value: 'Tab 3', + icon: , + direction: 'row', + }, + ], + }, +} diff --git a/src/components/tabs/Tabs.tsx b/src/components/tabs/Tabs.tsx index 883c327..61de75f 100644 --- a/src/components/tabs/Tabs.tsx +++ b/src/components/tabs/Tabs.tsx @@ -36,7 +36,7 @@ export const Tabs = forwardRef< /** * @default "primary" */ - variant?: 'primary' | 'secondary' + variant?: 'primary' | 'secondary' | 'block' full?: boolean }> >(function Tab( @@ -68,7 +68,10 @@ export const Tabs = forwardRef< if (!item) return - const indicatorWidth = variant === 'secondary' ? item.clientWidth : 36 + const indicatorWidth = + variant === 'secondary' || variant === 'block' + ? item.clientWidth + : 36 setWidth(`${indicatorWidth}px`) const left = item.offsetLeft + (item.clientWidth - indicatorWidth) / 2 setLeft(`${left}px`) @@ -131,6 +134,9 @@ export const Tabs = forwardRef< setValue(item.value)} diff --git a/src/components/tabs/tabs.scss b/src/components/tabs/tabs.scss index 48315ff..b351599 100644 --- a/src/components/tabs/tabs.scss +++ b/src/components/tabs/tabs.scss @@ -20,8 +20,8 @@ user-select: none; cursor: pointer; overflow: hidden; - - padding: 0.5rem 1rem 0.8rem 1rem; + padding: 0.5rem 1rem; + padding-bottom: 0.8rem; // for indicator display: inline-flex; align-items: center; flex-direction: column; @@ -86,6 +86,11 @@ bottom: -3px; // left: calc in js } + &[data-sd-variant='primary'] { + .sd-tabs-active_indicator { + clip-path: inset(0 0 50% 0); + } + } &[data-sd-variant='secondary'] { .sd-tabs-active_indicator { // width: calc in js @@ -94,4 +99,21 @@ bottom: 0; } } + &[data-sd-variant='block'] { + border-radius: 8px; + overflow: hidden; + background-color: var(--md-sys-color-surface-container-highest); + .sd-tabs-item { + background-color: transparent; + z-index: 1; + padding-bottom: 0.5rem; // reset + } + .sd-tabs-active_indicator { + inset: 0; + height: 100%; + width: 100%; + background-color: var(--md-sys-color-background); + clip-path: inset(2px round 4px); + } + } } diff --git a/src/composition/Skeleton/Skeleton.scss b/src/composition/Skeleton/Skeleton.scss new file mode 100644 index 0000000..eba2f73 --- /dev/null +++ b/src/composition/Skeleton/Skeleton.scss @@ -0,0 +1,14 @@ +.sd-skeleton { + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: sd-skeleton-shimmer 1.5s infinite ease-out; +} + +@keyframes sd-skeleton-shimmer { + 0% { + background-position: 100% 0; + } + 100% { + background-position: -100% 0; + } +} diff --git a/src/composition/Skeleton/Skeleton.stories.tsx b/src/composition/Skeleton/Skeleton.stories.tsx new file mode 100644 index 0000000..c83e048 --- /dev/null +++ b/src/composition/Skeleton/Skeleton.stories.tsx @@ -0,0 +1,19 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { Skeleton } from './Skeleton' + +const meta: Meta = { + title: 'composition/Skeleton', + component: Skeleton, + tags: ['autodocs'], +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + height: '2rem', + borderRadius: '4px', + }, +} diff --git a/src/composition/Skeleton/Skeleton.tsx b/src/composition/Skeleton/Skeleton.tsx new file mode 100644 index 0000000..cc22427 --- /dev/null +++ b/src/composition/Skeleton/Skeleton.tsx @@ -0,0 +1,9 @@ +import { forwardRef } from 'react' +import './Skeleton.scss' + +export const Skeleton = forwardRef< + HTMLDivElement, + Partial +>(({ ...style }) => { + return
+}) diff --git a/src/composition/Skeleton/index.ts b/src/composition/Skeleton/index.ts new file mode 100644 index 0000000..4220e69 --- /dev/null +++ b/src/composition/Skeleton/index.ts @@ -0,0 +1 @@ +export * from './Skeleton' diff --git a/src/documentation/ColorSchemes.mdx b/src/documentation/ColorSchemes.mdx index d034cef..c0ce3d0 100644 --- a/src/documentation/ColorSchemes.mdx +++ b/src/documentation/ColorSchemes.mdx @@ -1,7 +1,6 @@ import { ChangeTheme } from './components/ChangeTheme' import { ColorStatic } from './components/ColorSchemes' -
@@ -9,4 +8,4 @@ import { ColorStatic } from './components/ColorSchemes' Refer to [https://m3.material.io/styles/color/static/baseline](https://m3.material.io/styles/color/static/baseline) - \ No newline at end of file + diff --git a/src/documentation/Fonts.mdx b/src/documentation/Fonts.mdx index fdb6e17..e0b8edc 100644 --- a/src/documentation/Fonts.mdx +++ b/src/documentation/Fonts.mdx @@ -26,4 +26,4 @@ Chinese user may prefer: * { font-family: 'Google Sans', sans-serif; } -``` \ No newline at end of file +``` diff --git a/src/documentation/Icons.mdx b/src/documentation/Icons.mdx index bcf44b5..01e57be 100644 --- a/src/documentation/Icons.mdx +++ b/src/documentation/Icons.mdx @@ -1,7 +1,7 @@ # Icons This library uses the [MDI Icon Library](https://pictogrammers.com/library/mdi/). -You can refer to it at [Material Design Icons](https://materialdesignicons.com/). +You can refer to it at [Material Design Icons](https://materialdesignicons.com/). ```tsx import { mdiMagnify } from '@mdi/js' @@ -16,4 +16,4 @@ const App = () => ( ) ``` -A replacement is icons from [Google fonts](https://fonts.google.com/icons). \ No newline at end of file +A replacement is icons from [Google fonts](https://fonts.google.com/icons). diff --git a/src/documentation/Theming.mdx b/src/documentation/Theming.mdx index 96c574a..4496044 100644 --- a/src/documentation/Theming.mdx +++ b/src/documentation/Theming.mdx @@ -1,6 +1,6 @@ # Theming -This library uses the official material design css variables (`--md-sys-color-`, at `:root`) to theming. +This library uses the official material design css variables (`--md-sys-color-`, at `:root`) to theming. ```ts // create theme @@ -19,7 +19,11 @@ It's actually a module that provides some helper function and re-export the [@ma Here is a demo showing these wrapper functions, which can make theming easier. ```tsx -import { applyThemeForSoda, themeFromHexString, themeFromImageOrFile } from 'soda/dist/utils/theme' +import { + applyThemeForSoda, + themeFromHexString, + themeFromImageOrFile, +} from 'soda/dist/utils/theme' // simply applyThemeForSoda('#f82506') @@ -53,4 +57,4 @@ function SelectThemeFromFileButton() { } return } -``` \ No newline at end of file +``` diff --git a/src/documentation/ZIndex.mdx b/src/documentation/ZIndex.mdx index eab62c7..2a5f7f7 100644 --- a/src/documentation/ZIndex.mdx +++ b/src/documentation/ZIndex.mdx @@ -1,9 +1,9 @@ -import { Table } from "../composition/Table" +import { Table } from '../composition/Table' # zIndex Some components feature a `fixed` boolean property, which, when set to `true`, changes the component's position to `position: fixed`. -Additionally, while components come with a default `zIndex` value, this can be overridden by setting the `zIndex` property. +Additionally, while components come with a default `zIndex` value, this can be overridden by setting the `zIndex` property. The components also expose an `inset` property, allowing for precise control over their positioning. ```tsx @@ -16,13 +16,27 @@ Currently, the default `zIndex` is: - + + + + - - - - + + + + + + + + + + + + + + + +
ComponentzIndex
ComponentzIndex
snackbar1
app-bar1
navigation2
sheet3
snackbar1
app-bar1
navigation2
sheet3
- \ No newline at end of file diff --git a/src/documentation/components/Demo.tsx b/src/documentation/components/Demo.tsx index 1361cd2..97af3c1 100644 --- a/src/documentation/components/Demo.tsx +++ b/src/documentation/components/Demo.tsx @@ -65,7 +65,6 @@ function LayoutNavigationDrawer({ children }: { children?: React.ReactNode }) { if (!div.className.includes('sd-')) return div.classList.add('sb-unstyled') }) - }, [isScreenExpanded]) const containerRef = useRef(null) const [fullscreen, setFullscreen] = useFullscreen(containerRef)