Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/design-system-preview.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Design system / Storybook preview

on:
pull_request:
branches:
- "**"
paths:
- "assets/design-system/**"
- ".github/workflows/design-system-preview.yaml"

permissions:
checks: write
contents: read
pull-requests: write

jobs:
preview:
name: Create preview
if: ${{ github.actor != 'renovate[bot]' }}
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: assets
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
with:
node-version: 24.11.1
- run: yarn --immutable
- run: yarn workspace @pluralsh/design-system build:storybook
- uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0.11.0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_PLURALSH_DESIGN }}
projectId: pluralsh-design
entryPoint: assets/design-system
5 changes: 5 additions & 0 deletions assets/design-system/.firebaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "pluralsh-design"
}
}
20 changes: 20 additions & 0 deletions assets/design-system/firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"emulators": {
"hosting": {
"port": 5000,
"host": "0.0.0.0"
}
},
"hosting": {
"public": "storybook-static",
"ignore": [
"firebase.json"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
4 changes: 4 additions & 0 deletions assets/design-system/src/GlobalStyle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const {

export const colorsToCSSVars: (colors: unknown) => any = (colors) => {
function inner(colors: unknown, prefix = '') {
if (!colors || typeof colors !== 'object') {
return
}

Object.entries(colors).forEach(([key, value]) => {
if (typeof value === 'string') {
;(cssVars as any)[`--color-${prefix}${key}`] = value
Expand Down
14 changes: 7 additions & 7 deletions assets/design-system/src/components/AppIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export function toInitials(name: string) {
.map((n) => n.charAt(0).toUpperCase())

if (initials.length > 2) {
initials = [initials[0], last(initials)]
initials = [initials[0], last(initials) ?? '']
}

return initials.join('')
Expand All @@ -101,17 +101,17 @@ const AppIconSC = styled.div<{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme.colors[$color],
backgroundColor: $color ? theme.colors[$color] : undefined,
borderRadius: theme.borderRadiuses.medium,
border: $hasBorder ? theme.borders.default : 'none',
borderColor: theme.colors[$borderColor],
borderColor: $borderColor ? theme.colors[$borderColor] : undefined,
width: $boxSize,
height: $boxSize,
minWidth: $boxSize,
minHeight: $boxSize,
cursor: $clickable ? 'pointer' : 'auto',
overflow: 'hidden',
_hover: $clickable ? { backgroundColor: $borderColor } : null,
_hover: $clickable ? { backgroundColor: $borderColor } : undefined,
}))

const InitialsSC = styled.div<{
Expand Down Expand Up @@ -141,7 +141,7 @@ function AppIcon({
hue,
clickable = false,
url,
icon = null,
icon,
alt,
name,
initials,
Expand Down Expand Up @@ -175,13 +175,13 @@ function AppIcon({
$hasBorder={hasBorder}
$boxSize={boxSize}
$clickable={clickable}
onClick={clickable ? onClose : null}
onClick={clickable ? onClose : undefined}
{...props}
>
{url ? (
<ImgSC
src={url}
alt={alt}
alt={alt ?? undefined}
$iconWidth={iconWidth}
/>
) : (
Expand Down
2 changes: 1 addition & 1 deletion assets/design-system/src/components/ArrowScroll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function ArrowScroll({
color?: SemanticColorKey
opacity?: number
} & ComponentPropsWithRef<'div'>) {
const containerRef = useRef<HTMLDivElement>(undefined)
const containerRef = useRef<HTMLDivElement>(null)
const [showLeftGradient, setShowLeftGradient] = useState(false)
const [showRightGradient, setShowRightGradient] = useState(false)

Expand Down
8 changes: 4 additions & 4 deletions assets/design-system/src/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,14 @@ export function DynamicBreadcrumbs({
minLength = 0,
maxLength = Infinity,
collapsible = true,
breadcrumbs,
breadcrumbs = [],
wrapperRef: transitionRef,
...props
}: BreadcrumbPropsBase & {
wrapperRef?: RefObject<HTMLDivElement>
wrapperRef?: RefObject<HTMLDivElement | null>
style: any
}) {
const wrapperRef = useRef<HTMLDivElement | undefined>(undefined)
const wrapperRef = useRef<HTMLDivElement | null>(null)
const [visibleListId, setVisibleListId] = useState<string>('')
const children: ReactNode[] = []

Expand Down Expand Up @@ -403,7 +403,7 @@ export function Breadcrumbs({
}: BreadcrumbsProps & Omit<NavProps, 'ref'>) {
const contextCrumbs = useContext(BreadcrumbsContext)?.breadcrumbs
const breadcrumbs = propsCrumbs || contextCrumbs
const nodeRef = useRef<HTMLDivElement>(undefined)
const nodeRef = useRef<HTMLDivElement>(null)

if (!breadcrumbs) {
throw Error(
Expand Down
2 changes: 1 addition & 1 deletion assets/design-system/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ const Button = memo(
$size={buttonSize}
$type={buttonType}
$noPadding={props.padding === 'none'}
disabled={disabled}
disabled={disabled ?? undefined}
css={{
width,
minWidth,
Expand Down
2 changes: 1 addition & 1 deletion assets/design-system/src/components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ function Card({
<HeaderSC
$fillLevel={headerFillLevel}
$selected={selected}
$size={size}
$size={size ?? 'medium'}
$cornerSize={cornerSize}
{...headerProps}
>
Expand Down
12 changes: 6 additions & 6 deletions assets/design-system/src/components/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function Checkbox({
}
const labelId = useId()
const toggleState = useToggleState(toggleStateProps)
const inputRef = useRef<any>(undefined)
const inputRef = useRef<any>(null)
const { isFocusVisible, focusProps } = useFocusRing()
const { inputProps } = useCheckbox(
{
Expand All @@ -195,9 +195,9 @@ function Checkbox({
)

const icon = indeterminate ? (
<IndeterminateIcon small={small} />
<IndeterminateIcon small={!!small} />
) : toggleState.isSelected ? (
<CheckedIcon small={small} />
<CheckedIcon small={!!small} />
) : null

return (
Expand All @@ -209,8 +209,8 @@ function Checkbox({
indeterminate,
})}
$isFocusVisible={isFocusVisible}
$small={small}
$disabled={disabled}
$small={!!small}
$disabled={!!disabled}
display="flex"
marginBottom="0"
{...props}
Expand All @@ -224,7 +224,7 @@ function Checkbox({
if (typeof onChange === 'function') {
onChange(e)
}
inputProps.onChange(e)
inputProps.onChange?.(e)
}}
ref={inputRef}
/>
Expand Down
22 changes: 14 additions & 8 deletions assets/design-system/src/components/Checklist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ type ChecklistProps = ComponentPropsWithRef<'div'> & {
}

type ChecklistStateProps = {
onSelectionChange?: Dispatch<number>
onSelectionChange?: Dispatch<number | null>
onFocusChange?: Dispatch<number>
onOpenChange?: Dispatch<boolean>
selectedKey?: number
selectedKey?: number | null
focusedKey?: number
completedKey?: number
isOpen?: boolean
Expand Down Expand Up @@ -123,13 +123,17 @@ function ChecklistUnstyled({
useState<number>(-1)

const onSelectionChangeWrapper = useCallback(
(idx: number) =>
idx < children.length && idx > -1 ? onSelectionChange(idx) : undefined,
(idx: number | null) => {
if (idx !== null && (idx >= children.length || idx < 0)) return
onSelectionChange?.(idx)
},
[children, onSelectionChange]
)
const onFocusChangeWrapper = useCallback(
(idx: number) =>
idx < children.length && idx > -1 ? onFocusChange(idx) : undefined,
(idx: number) => {
if (idx >= children.length || idx < -1) return
onFocusChange?.(idx)
},
[children, onFocusChange]
)

Expand All @@ -142,7 +146,7 @@ function ChecklistUnstyled({
index={index}
selected={selectedKey === index}
focused={focusedKey === index}
completed={completedKey >= index}
completed={(completedKey ?? -1) >= index}
onSelectionChange={onSelectionChangeWrapper}
onFocusChange={onFocusChangeWrapper}
>
Expand Down Expand Up @@ -170,6 +174,8 @@ function ChecklistUnstyled({
})

useEffect(() => {
if (!itemsContainerRef.current || !finishedContainerRef.current) return

const maxItemContainerHeight = Math.max(
itemContainerHeight,
itemsContainerRef.current.getBoundingClientRect().height
Expand Down Expand Up @@ -202,7 +208,7 @@ function ChecklistUnstyled({
>
<div
className="header"
onClick={() => onOpenChange(!isOpen)}
onClick={() => onOpenChange?.(!isOpen)}
>
<div>{label}</div>
<DropdownArrowIcon className={isOpen ? 'arrowUp' : 'arrowDown'} />
Expand Down
6 changes: 3 additions & 3 deletions assets/design-system/src/components/ChecklistItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ type ChecklistItemInnerProps = Omit<ChecklistItemProps, 'children'> & {
selected?: boolean
focused?: boolean
completed?: boolean
onSelectionChange: Dispatch<number>
onSelectionChange: Dispatch<number | null>
onFocusChange: Dispatch<number>
}

Expand All @@ -184,7 +184,7 @@ function ChecklistItemInnerUnstyled({
onFocusChange,
...props
}: ChecklistItemInnerProps): JSX.Element {
const headerRef = useRef<HTMLDivElement>(undefined)
const headerRef = useRef<HTMLDivElement>(null)
const { keyboardProps } = useKeyboard({
onKeyDown: (e) => {
switch (e.key) {
Expand All @@ -209,7 +209,7 @@ function ChecklistItemInnerUnstyled({

useEffect(() => {
if (headerRef.current && focused) {
setTimeout(() => headerRef.current.focus())
setTimeout(() => headerRef.current?.focus())
}
}, [headerRef, focused])

Expand Down
2 changes: 1 addition & 1 deletion assets/design-system/src/components/ChipList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function ChipList<TValue = string>({
<Chip
key={(v as any).key || i}
clickable={clickable}
onClick={() => clickable && onClick(v)}
onClick={() => clickable && onClick?.(v)}
{...props}
>
{transformValue ? transformValue(v) : `${v}`}
Expand Down
Loading
Loading