From 7a6d4f10af1af407db309846b0f74727de90f668 Mon Sep 17 00:00:00 2001 From: Jo du Plessis Date: Sun, 10 Mar 2024 16:27:21 +0200 Subject: [PATCH] refactor: general improvements & bug fixes (#70) closes #69 closes #71 closes #72 closes #73 closes #74 closes #75 closes #76 closes #77 closes #78 closes #79 closes #80 closes #81 closes #82 closes #83 closes #84 closes #85 closes #86 --- package.json | 2 +- packages/core/package.json | 2 +- packages/core/src/accordion/accordion.css | 2 +- packages/core/src/attachment/attachment.css | 14 +- .../src/attachment/attachment.stories.tsx | 8 -- packages/core/src/avatar/avatar.stories.tsx | 1 - packages/core/src/badge/badge.css | 53 +++++++- packages/core/src/badge/badge.stories.tsx | 22 ++-- packages/core/src/badge/badge.tsx | 6 +- packages/core/src/button/button.css | 121 +++++++++++++++--- packages/core/src/button/button.stories.tsx | 5 +- packages/core/src/card/card.css | 2 +- packages/core/src/checkbox/checkbox.css | 4 +- packages/core/src/color/color.css | 4 +- packages/core/src/cookie/cookie.stories.tsx | 1 + packages/core/src/copy/copy.css | 2 +- packages/core/src/date-time/date-time.css | 13 ++ .../core/src/date-time/date-time.stories.tsx | 1 - packages/core/src/date-time/date-time.tsx | 5 +- packages/core/src/input/input.css | 12 +- packages/core/src/input/input.stories.tsx | 3 +- packages/core/src/input/input.tsx | 18 ++- packages/core/src/kbd/kbd.css | 2 +- packages/core/src/layout/layout.css | 8 +- packages/core/src/menu/menu.css | 10 +- packages/core/src/modal/modal.css | 12 +- packages/core/src/modal/modal.stories.tsx | 36 ++++++ packages/core/src/modal/modal.tsx | 6 +- packages/core/src/navigation/navigation.css | 8 +- packages/core/src/pagination/pagination.css | 4 +- packages/core/src/pill/pill.css | 2 +- packages/core/src/pill/pill.tsx | 23 ++-- packages/core/src/popover/popover.css | 2 +- packages/core/src/radio/radio.css | 2 +- packages/core/src/select/select.css | 6 +- packages/core/src/styles/popout.css | 38 +++--- packages/core/src/styles/reset.css | 4 +- packages/core/src/table/table.css | 2 +- packages/core/src/tabs/tabs.css | 61 +++++++-- packages/core/src/tabs/tabs.stories.tsx | 77 +++++++---- packages/core/src/tabs/tabs.tsx | 89 +++++++++---- packages/core/src/task/task.css | 10 +- packages/core/src/text/text.css | 15 +++ packages/core/src/textarea/textarea.css | 2 +- packages/core/src/textarea/textarea.tsx | 2 +- packages/core/src/timeline/timeline.css | 6 +- .../core/src/timeline/timeline.stories.tsx | 10 +- packages/core/src/upload/upload.css | 6 +- packages/design/package.json | 2 +- packages/design/tokens/font.json | 4 +- 50 files changed, 546 insertions(+), 204 deletions(-) diff --git a/package.json b/package.json index f483a044..48a0451c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "fold-dev", "title": "Fold", - "version": "0.4.0", + "version": "0.5.0", "description": "The UI library for product teams.", "workspaces": { "packages": [ diff --git a/packages/core/package.json b/packages/core/package.json index 534fad95..dca8b6f4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@fold-dev/core", "title": "Fold", - "version": "0.4.0", + "version": "0.5.0", "description": "The UI library for product teams.", "main": "dist/index.js", "module": "dist/index.js", diff --git a/packages/core/src/accordion/accordion.css b/packages/core/src/accordion/accordion.css index 7fd7dda1..28ca1b64 100644 --- a/packages/core/src/accordion/accordion.css +++ b/packages/core/src/accordion/accordion.css @@ -1,7 +1,7 @@ :root { --f-accordion-border-radius: var(--f-radius); --f-accordion-border-color: var(--f-color-border); - --f-accordion-border-width: 0.1rem; + --f-accordion-border-width: 1px; --f-accordion-background: var(--f-color-surface); --f-accordion-color: var(--f-color-text-weak); --f-accordion-color-description: var(--f-color-text-weakest); diff --git a/packages/core/src/attachment/attachment.css b/packages/core/src/attachment/attachment.css index 5fee73df..86997182 100644 --- a/packages/core/src/attachment/attachment.css +++ b/packages/core/src/attachment/attachment.css @@ -19,7 +19,7 @@ position: relative; cursor: pointer; min-height: var(--f-size-12); - border: 0.1rem solid; + border: 1px solid; border-color: var(--f-attachment-border-color); border-radius: var(--f-attachment-border-radius); padding: var(--f-space-2); @@ -70,14 +70,17 @@ .f-attachment__text { flex: 1; - min-height: var(--f-size-11); align-items: flex-start; } /* hack to remove padding from the bottom on default settings so the icon sites flush */ .f-attachment__text > * + * { - margin-top: -2px; + margin-top: 2px; +} + +.f-attachment.sm .f-attachment__text > * + * { + margin-top: 0px; } .f-attachment__text-meta { @@ -97,6 +100,7 @@ } /* sizes */ +/* xs & xl not supported yet */ .f-attachment.xs .f-attachment__icon { width: var(--f-size-8); @@ -132,7 +136,7 @@ color: var(--f-attachment-color); position: relative; min-height: var(--f-size-12); - border: 0.1rem solid; + border: 1px solid; border-color: var(--f-attachment-border-color); border-radius: var(--f-attachment-border-radius); width: var(--f-attachment-thumb-size); @@ -182,7 +186,7 @@ border-radius: var(--f-attachment-border-radius); width: 100%; height: 100%; - border: 0.1rem solid transparent; + border: 1px solid transparent; gap: var(--f-space-1); } diff --git a/packages/core/src/attachment/attachment.stories.tsx b/packages/core/src/attachment/attachment.stories.tsx index 440627c9..bb5015f7 100644 --- a/packages/core/src/attachment/attachment.stories.tsx +++ b/packages/core/src/attachment/attachment.stories.tsx @@ -137,14 +137,6 @@ export const Size = () => ( gap={10}> - ( ( gap={5} width="fit-content"> +34 notifications - +12 bordered notifications + +12 outline notifications ) @@ -43,40 +43,40 @@ export const Variants = () => ( // -- -export const VariantsBordered = () => ( +export const VariantsOutline = () => ( - default + default + outline> accent + outline> success + outline> neutral + outline> caution + outline> warning + outline> danger @@ -141,22 +141,18 @@ export const Position = () => ( ) diff --git a/packages/core/src/badge/badge.tsx b/packages/core/src/badge/badge.tsx index 1a7db938..8a5fd827 100644 --- a/packages/core/src/badge/badge.tsx +++ b/packages/core/src/badge/badge.tsx @@ -9,16 +9,16 @@ export type BadgeProps = { size?: Size variant?: Variant anchor?: BadgeAnchor - bordered?: boolean + outline?: boolean } & CoreViewProps export const Badge = (props: BadgeProps) => { - const { size = 'md', variant = 'default', anchor, bordered, ...rest } = props + const { size = 'md', variant = 'default', anchor, outline, ...rest } = props const className = classNames( { 'f-badge': true, 'f-row': true, - 'is-bordered': bordered, + 'is-outline': outline, 'no-children': !props.children, }, [props.className, getActionClass(variant), getActionClass(anchor), size] diff --git a/packages/core/src/button/button.css b/packages/core/src/button/button.css index a2f7e82a..208961a5 100644 --- a/packages/core/src/button/button.css +++ b/packages/core/src/button/button.css @@ -41,10 +41,6 @@ outline-offset: 1px; } -.f-button:active { - /* outline: var(--f-focus); */ -} - .f-button.is-active, .f-button:not(:disabled):hover { color: var(--f-button-color-hover); @@ -512,32 +508,119 @@ border-right: 0px; } -/* colors */ +/* colors - horizontal */ +/* TODO: find a better way to handle this */ + +.f-button-group.is-horizontal .f-button.is-accent:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-accent-weak); +} + +.f-button-group.is-horizontal .f-button.is-accent:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-accent); +} + +.f-button-group.is-horizontal .f-button.is-success:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-success-weak); +} + +.f-button-group.is-horizontal .f-button.is-success:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-success); +} + +.f-button-group.is-horizontal .f-button.is-neutral:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-neutral-weak); +} + +.f-button-group.is-horizontal .f-button.is-neutral:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-neutral); +} + +.f-button-group.is-horizontal .f-button.is-caution:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-caution-weak); +} + +.f-button-group.is-horizontal .f-button.is-caution:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-caution); +} + +.f-button-group.is-horizontal .f-button.is-warning:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-warning-weak); +} + +.f-button-group.is-horizontal .f-button.is-warning:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-warning); +} + +.f-button-group.is-horizontal .f-button.is-danger:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-danger-weak); +} + +.f-button-group.is-horizontal .f-button.is-danger:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-danger); +} + +.f-button-group.is-horizontal .f-button.is-highlight:not(.is-subtle):not(.is-outline) { + border-left-color: var(--f-color-highlight-weak); +} + +.f-button-group.is-horizontal .f-button.is-highlight:not(.is-subtle):not(.is-outline):first-child { + border-left-color: var(--f-color-highlight); +} + +/* colors - vertical */ + +.f-button-group.is-vertical .f-button.is-accent:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-accent-weak); +} + +.f-button-group.is-vertical .f-button.is-accent:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-accent); +} + +.f-button-group.is-vertical .f-button.is-success:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-success-weak); +} + +.f-button-group.is-vertical .f-button.is-success:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-success); +} + +.f-button-group.is-vertical .f-button.is-neutral:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-neutral-weak); +} + +.f-button-group.is-vertical .f-button.is-neutral:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-neutral); +} + +.f-button-group.is-vertical .f-button.is-caution:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-caution-weak); +} -.f-button-group .f-button.is-accent:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-accent-weak); +.f-button-group.is-vertical .f-button.is-caution:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-caution); } -.f-button-group .f-button.is-success:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-success-weak); +.f-button-group.is-vertical .f-button.is-warning:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-warning-weak); } -.f-button-group .f-button.is-neutral:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-neutral-weak); +.f-button-group.is-vertical .f-button.is-warning:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-warning); } -.f-button-group .f-button.is-caution:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-caution-weak); +.f-button-group.is-vertical .f-button.is-danger:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-danger-weak); } -.f-button-group .f-button.is-warning:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-warning-weak); +.f-button-group.is-vertical .f-button.is-danger:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-danger); } -.f-button-group .f-button.is-danger:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-danger-weak); +.f-button-group.is-vertical .f-button.is-highlight:not(.is-subtle):not(.is-outline) { + border-top-color: var(--f-color-highlight-weak); } -.f-button-group .f-button.is-highlight:not(.is-subtle):not(.is-outline) { - border-color: var(--f-color-highlight-weak); +.f-button-group.is-vertical .f-button.is-highlight:not(.is-subtle):not(.is-outline):first-child { + border-top-color: var(--f-color-highlight); } diff --git a/packages/core/src/button/button.stories.tsx b/packages/core/src/button/button.stories.tsx index fd44d6a9..f8360127 100644 --- a/packages/core/src/button/button.stories.tsx +++ b/packages/core/src/button/button.stories.tsx @@ -403,8 +403,9 @@ export const ButtonGroups = () => ( - - + + + { .f-date-picker__title .f-button__label .f-text { + width: 100%; + display: flex; + justify-content: stretch; + align-items: stretch; + align-content: stretch; + flex-direction: row; +} + .f-date-picker__titles > .f-date-picker__title .f-date-picker__title-text { flex: 1; + display: block; +} + +.f-date-picker__titles > .f-date-picker__title .f-date-picker__title-text:last-child { } /* scrolling date picker */ diff --git a/packages/core/src/date-time/date-time.stories.tsx b/packages/core/src/date-time/date-time.stories.tsx index bfc71d30..b8ee4c55 100644 --- a/packages/core/src/date-time/date-time.stories.tsx +++ b/packages/core/src/date-time/date-time.stories.tsx @@ -323,7 +323,6 @@ export const DateCellVariants = () => ( variant="accent" anchor="top-left" style={{ marginLeft: 5, marginTop: 5 }} - bordered /> diff --git a/packages/core/src/date-time/date-time.tsx b/packages/core/src/date-time/date-time.tsx index 22ba26f1..3bddd11e 100644 --- a/packages/core/src/date-time/date-time.tsx +++ b/packages/core/src/date-time/date-time.tsx @@ -839,7 +839,7 @@ export const DatePicker = (props: DatePickerProps) => { className={className}> + className="f-date-picker__titles f-row"> + + + + + Not this again... + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco + laboris nisi ut aliquip ex ea commodo consequat. + + + + + ) +} + +// -- + export const WithHeaderAndFooter = () => { const { visible, show, hide } = useVisibility(false) diff --git a/packages/core/src/modal/modal.tsx b/packages/core/src/modal/modal.tsx index 7b080523..91a714b3 100644 --- a/packages/core/src/modal/modal.tsx +++ b/packages/core/src/modal/modal.tsx @@ -36,6 +36,7 @@ export type ModalProps = { header?: ReactElement | ReactElement[] borderless?: boolean disableBackgroundDismiss?: boolean + noOverlay?: boolean portal?: any onDismiss?: any } & CoreViewProps @@ -49,6 +50,7 @@ export const Modal = (props: ModalProps) => { header, borderless = false, disableBackgroundDismiss = false, + noOverlay, portal, onDismiss, ...rest @@ -73,18 +75,20 @@ export const Modal = (props: ModalProps) => { }, [isVisible]) const renderModal = () => { + const classNameOverlay = "f-modal f-row" + (noOverlay ? " no-overlay" : "") const className = classNames( { 'f-modal__inner': true, 'f-col': true, 'is-borderless': borderless, + 'no-overlay': noOverlay, }, [props.className, getActionClass(anchor)] ) return (
hr { @@ -227,12 +227,12 @@ display: block; position: absolute; height: 100%; - top: calc(((var(--f-navbar-padding) / 2) * -1) - 0.1rem); + top: calc(((var(--f-navbar-padding) / 2) * -1) - 2px); width: 1px; color: transparent; background: transparent; border: none; - border-left: 0.1rem solid var(--f-color-border); + border-left: 1px solid var(--f-color-border); } .f-navigation.is-navbar > .f-navigation-item .f-navigation-item__container { diff --git a/packages/core/src/pagination/pagination.css b/packages/core/src/pagination/pagination.css index f0c72b88..f69164dc 100644 --- a/packages/core/src/pagination/pagination.css +++ b/packages/core/src/pagination/pagination.css @@ -8,7 +8,8 @@ --f-pagination-color-disabled: var(--f-color-text-weakest); --f-pagination-gap: 0.2rem; --f-pagination-min-width: 2.5rem; - --f-pagination-item-border: 0.1rem solid var(--f-color-border); + --f-pagination-height: 2.5rem; + --f-pagination-item-border: 1px solid var(--f-color-border); } .f-pagination { @@ -37,6 +38,7 @@ align-content: center; border: var(--f-pagination-item-border); min-width: var(--f-pagination-min-width); + height: var(--f-pagination-height); } .f-pagination__item > .f-icon { diff --git a/packages/core/src/pill/pill.css b/packages/core/src/pill/pill.css index 558c7ea0..07043b6a 100644 --- a/packages/core/src/pill/pill.css +++ b/packages/core/src/pill/pill.css @@ -2,7 +2,7 @@ --f-pill-spacing: 0rem; --f-pill-label-padding: 0 var(--f-space-2); --f-pill-buffer-icon: var(--f-space-1); - --f-pill-border-width: 0.1rem; + --f-pill-border-width: 1px; --f-pill-border-radius: var(--f-radius-full); --f-pill-color: var(--f-color-text-weaker); --f-pill-color-subtle: var(--f-color-text-weaker); diff --git a/packages/core/src/pill/pill.tsx b/packages/core/src/pill/pill.tsx index 86babd0e..b5dacb69 100644 --- a/packages/core/src/pill/pill.tsx +++ b/packages/core/src/pill/pill.tsx @@ -16,19 +16,18 @@ export type PillProps = { export const Pill = forwardRef((props: PillProps, ref) => { const { size = 'md', solid, outline, subtle, color, prefix, suffix, style = {}, ...rest } = props const isClickable = !!props.onClick - const accentColor = useMemo(() => { - if (outline || subtle) return color - return getForegroundColor(color) + const styles = useMemo(() => { + const accentColor = outline || subtle ? color : getForegroundColor(color) + const borderColor = color ? (subtle ? 'transparent' : outline ? color : 'transparent') : null + const backgroundColor = color ? (outline || subtle ? addAlpha(color, 0.15) : color) : null + return cleanObject({ + ...style, + color: accentColor, + '--f-pill-border-color': borderColor, + backgroundColor, + outlineColor: backgroundColor, + }) }, [color, outline, solid]) - const borderColor = color ? (subtle ? 'transparent' : outline ? color : 'transparent') : null - const backgroundColor = color ? (outline || subtle ? addAlpha(color, 0.15) : color) : null - const styles = cleanObject({ - ...style, - color: accentColor, - backgroundColor, - borderColor, - outlineColor: backgroundColor, - }) const className = classNames( { 'f-pill': true, diff --git a/packages/core/src/popover/popover.css b/packages/core/src/popover/popover.css index d90673d2..1dcae690 100644 --- a/packages/core/src/popover/popover.css +++ b/packages/core/src/popover/popover.css @@ -7,7 +7,7 @@ .f-popover { position: absolute; - border: 0.1rem solid; + border: 1px solid; border-color: var(--f-popover-border-color); border-radius: var(--f-popover-border-radius); background: var(--f-popover-background); diff --git a/packages/core/src/radio/radio.css b/packages/core/src/radio/radio.css index 1d61431a..0350f4c4 100644 --- a/packages/core/src/radio/radio.css +++ b/packages/core/src/radio/radio.css @@ -18,7 +18,7 @@ input.f-radio[type="radio"] { height: var(--f-size-5); width: var(--f-size-5); border-radius: var(--f-radio-border-radius); - border: 0.1rem solid; + border: 1px solid; border-color: var(--f-radio-border-color); background-color: var(--f-radio-background-color); display: grid; diff --git a/packages/core/src/select/select.css b/packages/core/src/select/select.css index 74049c1c..f960259b 100644 --- a/packages/core/src/select/select.css +++ b/packages/core/src/select/select.css @@ -25,6 +25,10 @@ z-index: 1; } +.f-select-container .f-input-control { + cursor: pointer; +} + input.f-select { cursor: pointer; color: var(--f-select-color); @@ -48,7 +52,7 @@ input.f-select:disabled { top: 100%; width: 100%; position: absolute; - border: 0.1rem solid; + border: 1px solid; border-color: var(--f-select-popover-border-color); border-radius: var(--f-select-popover-border-radius); background: var(--f-select-popover-background); diff --git a/packages/core/src/styles/popout.css b/packages/core/src/styles/popout.css index 41b8e326..9203c599 100644 --- a/packages/core/src/styles/popout.css +++ b/packages/core/src/styles/popout.css @@ -137,9 +137,9 @@ .f-popout-bottom-left.has-arrow:after { top: 0px; left: var(--f-radius); - border-left-width: 0.1rem; + border-left-width: 1px; border-right-width: 0rem; - border-top-width: 0.1rem; + border-top-width: 1px; border-bottom-width: 0rem; border-top-left-radius: var(--f-radius-sm); transform: translateY(-50%) rotate(45deg); @@ -148,9 +148,9 @@ .f-popout-bottom-right.has-arrow:after { top: 0px; right: var(--f-radius); - border-left-width: 0.1rem; + border-left-width: 1px; border-right-width: 0rem; - border-top-width: 0.1rem; + border-top-width: 1px; border-bottom-width: 0rem; border-top-left-radius: var(--f-radius-sm); transform: translateY(-50%) rotate(45deg); @@ -160,8 +160,8 @@ top: 100%; left: var(--f-radius); border-left-width: 0rem; - border-right-width: 0.1rem; - border-bottom-width: 0.1rem; + border-right-width: 1px; + border-bottom-width: 1px; border-top-width: 0rem; border-bottom-right-radius: var(--f-radius-sm); transform: translateY(-50%) rotate(45deg); @@ -171,19 +171,19 @@ top: 100%; right: var(--f-radius); border-left-width: 0rem; - border-right-width: 0.1rem; - border-bottom-width: 0.1rem; + border-right-width: 1px; + border-bottom-width: 1px; border-top-width: 0rem; border-bottom-right-radius: var(--f-radius-sm); transform: translateY(-50%) rotate(45deg); } .f-popout-bottom-center.has-arrow:after { - top: 0%; + top: -1px; right: 50%; - border-left-width: 0.1rem; + border-left-width: 1px; border-right-width: 0rem; - border-top-width: 0.1rem; + border-top-width: 1px; border-bottom-width: 0rem; border-top-left-radius: var(--f-radius-sm); transform: translateY(-50%) translateX(50%) rotate(45deg); @@ -193,8 +193,8 @@ top: 100%; right: 50%; border-left-width: 0rem; - border-right-width: 0.1rem; - border-bottom-width: 0.1rem; + border-right-width: 1px; + border-bottom-width: 1px; border-top-width: 0rem; border-bottom-right-radius: var(--f-radius-sm); transform: translateY(-50%) translateX(50%) rotate(45deg); @@ -202,10 +202,10 @@ .f-popout-middle-left.has-arrow:after { top: 50%; - right: 0.1rem; + right: -1px; border-left-width: 0rem; - border-right-width: 0.1rem; - border-top-width: 0.1rem; + border-right-width: 1px; + border-top-width: 1px; border-bottom-width: 0rem; border-top-right-radius: var(--f-radius-sm); transform: translateY(-50%) translateX(50%) rotate(45deg); @@ -213,10 +213,10 @@ .f-popout-middle-right.has-arrow:after { top: 50%; - left: 0.1rem; - border-left-width: 0.1rem; + left: -1px; + border-left-width: 1px; border-right-width: 0rem; - border-bottom-width: 0.1rem; + border-bottom-width: 1px; border-top-width: 0rem; border-bottom-left-radius: var(--f-radius-sm); transform: translateY(-50%) translateX(-50%) rotate(45deg); diff --git a/packages/core/src/styles/reset.css b/packages/core/src/styles/reset.css index 83e849d9..42670c83 100644 --- a/packages/core/src/styles/reset.css +++ b/packages/core/src/styles/reset.css @@ -1,9 +1,9 @@ html, body { background-color: transparent; box-sizing: border-box; - font-size: 15px; + font-size: 14px; font-weight: normal; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; + font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji" } *, diff --git a/packages/core/src/table/table.css b/packages/core/src/table/table.css index 34858194..25562241 100644 --- a/packages/core/src/table/table.css +++ b/packages/core/src/table/table.css @@ -69,7 +69,7 @@ table.f-table.is-striped tr:nth-child(even) td { } table.f-table.is-lined tr td { - border-top: 0.1rem solid; + border-top: 1px solid; border-color: var(--f-table-border-color); } diff --git a/packages/core/src/tabs/tabs.css b/packages/core/src/tabs/tabs.css index 2edc6227..1c68f8c2 100644 --- a/packages/core/src/tabs/tabs.css +++ b/packages/core/src/tabs/tabs.css @@ -2,13 +2,15 @@ --f-tabs-color-icon: var(--f-color-text-weakest); --f-tabs-panel-border-color: var(--f-color-border); --f-tabs-panel-padding: var(--f-space-6); - --f-tabs-tab-padding: var(--f-space-3); + --f-tabs-tab-padding: var(--f-space-4); + --f-tabs-tab-height: var(--f-space-11); --f-tabs-tab-color: var(--f-color-text-weak); --f-tabs-tab-active: var(--f-color-accent); --f-tabs-tab-disabled-color: var(--f-color-text-weakest); --f-tabs-tab-background-hover: var(--f-color-surface-strong); - --f-tabs-icon-padding: var(--f-space-inset-x-2); - --f-tabs-arrow-padding: var(--f-space-inset-x-1); + --f-tabs-tab-scroll-button-background: var(--f-color-surface); + --f-tabs-tab-list-background: var(--f-color-surface); + --f-tabs-tab-scroll-button-padding: var(--f-size-5); --f-tab-ix-spacing: 0.5rem; --f-tab-inner-width: fit-content; } @@ -27,7 +29,7 @@ .f-tab-list { color: var(--f-tabs-color-icon); - + background: var(--f-tabs-tab-list-background); } .f-tab-list * { @@ -35,23 +37,61 @@ } .f-tab-list.is-left { - border-right: 0.1rem solid var(--f-tabs-panel-border-color); + border-right: 1px solid var(--f-tabs-panel-border-color); } .f-tab-list.is-right { - border-left: 0.1rem solid var(--f-tabs-panel-border-color); + border-left: 1px solid var(--f-tabs-panel-border-color); } .f-tab-list.is-top { - border-bottom: 0.1rem solid var(--f-tabs-panel-border-color); + border-bottom: 1px solid var(--f-tabs-panel-border-color); } .f-tab-list.is-bottom { - border-top: 0.1rem solid var(--f-tabs-panel-border-color); + border-top: 1px solid var(--f-tabs-panel-border-color); } +/* overflow icon */ + .f-tab-list__icon { - padding: var(--f-tabs-arrow-padding); + position: absolute; + z-index: 2; +} + +.f-tab-list.is-horizontal .f-tab-list__icon.is-start { + left: 0; + height: 100%; + padding-right: var(--f-tabs-tab-scroll-button-padding); + background: linear-gradient(to right, var(--f-tabs-tab-scroll-button-background) 50%, transparent 100%); +} + +.f-tab-list.is-horizontal .f-tab-list__icon.is-end { + right: 0; + height: 100%; + padding-left: var(--f-tabs-tab-scroll-button-padding); + background: linear-gradient(to left, var(--f-tabs-tab-scroll-button-background) 50%, transparent 100%); +} + +.f-tab-list.is-vertical .f-tab-list__icon.is-start { + top: 0; + padding-bottom: var(--f-tabs-tab-scroll-button-padding); + background: linear-gradient(to bottom, var(--f-tabs-tab-scroll-button-background) 50%, transparent 100%); + width: 100%; +} + +.f-tab-list.is-vertical .f-tab-list__icon.is-end { + bottom: 0; + padding-top: var(--f-tabs-tab-scroll-button-padding); + background: linear-gradient(to top, var(--f-tabs-tab-scroll-button-background) 50%, transparent 100%); + width: 100%; +} + +.f-tab-list.is-vertical .f-tab-list__icon.is-start .f-button, +.f-tab-list.is-vertical .f-tab-list__icon.is-end .f-button { + max-width: 5rem; + width: 60%; + min-width: 3rem; } /* animated */ @@ -151,13 +191,14 @@ .f-tab { background: transparent; - padding: var(--f-tabs-tab-padding); + padding: 0 var(--f-tabs-tab-padding); color: var(--f-tabs-tab-color); position: relative; outline: none; cursor: pointer; flex-grow: 1; gap: var(--f-tab-ix-spacing); + min-height: var(--f-tabs-tab-height); } .f-tab:focus, diff --git a/packages/core/src/tabs/tabs.stories.tsx b/packages/core/src/tabs/tabs.stories.tsx index 11a8866c..40b2d9d3 100644 --- a/packages/core/src/tabs/tabs.stories.tsx +++ b/packages/core/src/tabs/tabs.stories.tsx @@ -1,4 +1,4 @@ -import { Badge, Card, Heading, IconLib, Pill, Stack, Tab, TabList, TabPanel, TabPanels, Tabs } from '@fold-dev/core' +import { Badge, Card, Heading, IconLib, Pill, Stack, Tab, TabList, TabPanel, TabPanels, Tabs, View } from '@fold-dev/core' import React, { useState } from 'react' export default { @@ -118,27 +118,60 @@ export const Overflow = () => { const [selected, setSelected] = useState(0) return ( - - - Profile - Settings - Security - Privacy - Subscription - Overflow - - - Profile related content - Settings related content - Security related content - Privacy related content - Subscription related content - Overflow related content - - + + + + Profile + Settings + Security + Privacy + Subscription + Overflow + + + Profile related content + Settings related content + Security related content + Privacy related content + Subscription related content + Overflow related content + + + + + + Profile + Settings + Security + Privacy + Subscription + Membership + Account + + + Profile related content + Settings related content + Security related content + Privacy related content + Subscription related content + Membership related content + Account related content + + + ) } diff --git a/packages/core/src/tabs/tabs.tsx b/packages/core/src/tabs/tabs.tsx index 92dedccb..4a8b2171 100644 --- a/packages/core/src/tabs/tabs.tsx +++ b/packages/core/src/tabs/tabs.tsx @@ -9,8 +9,8 @@ import React, { useRef, useState, } from 'react' -import { IconLib, useId, View } from '..' -import { classNames, getActionClass, getOffset, renderChildren } from '../helpers' +import { Button, ButtonProps, IconLib, useId, View } from '..' +import { classNames, getActionClass, getOffset, renderChildren, waitForRender } from '../helpers' import { useResize } from '../hooks/resize.hook' import { Text } from '../text/text' import { CoreViewProps, Size } from '../types' @@ -93,6 +93,7 @@ export type TabListProps = { layout?: 'bottom' | 'top' | 'left' | 'right' selected?: number onSelect?: (index: number) => void + scrollButtonProps?: ButtonProps icons?: any } & Omit @@ -101,10 +102,11 @@ export const TabList = (props: TabListProps) => { stretch, disableScroll, animated, - scrollJump = 100, + scrollJump = 120, layout = 'top', selected, onSelect, + scrollButtonProps = {}, icons = { moreV: 'chevron-down', lessV: 'chevron-up', @@ -115,7 +117,8 @@ export const TabList = (props: TabListProps) => { } = props const { box } = useContext(TabsContext) const listRef = useRef(null) - const [overflow, setOverflow] = useState(false) + const [overflowStart, setOverflowStart] = useState(false) + const [overflowEnd, setOverflowEnd] = useState(false) const isRow = layout == 'top' || layout == 'bottom' const isCol = layout == 'left' || layout == 'right' const iconMore = isRow ? icons.lessH : icons.lessV @@ -124,6 +127,8 @@ export const TabList = (props: TabListProps) => { const className = classNames( { 'f-tab-list': true, + 'is-vertical': isCol, + 'is-horizontal': isRow, 'f-row': isRow, 'f-col': isCol, 'is-stretch': stretch, @@ -155,14 +160,47 @@ export const TabList = (props: TabListProps) => { } } - useLayoutEffect(() => { - if (disableScroll) return + const toggleRowButtonVisibility = (element) => { + setOverflowStart(element.scrollLeft > 0) + setOverflowEnd(element.scrollLeft < element.scrollWidth - element.offsetWidth) + } + + const toggleColButtonVisibility = (element) => { + setOverflowStart(element.scrollTop > 0) + setOverflowEnd(element.scrollTop < element.scrollHeight - element.offsetHeight - 1) // TODO: why the +1? + } + + const calculateScroll = () => { + if (disableScroll) { + setOverflowStart(false) + setOverflowEnd(false) + return + } + + // if there is overflow for rows if (isRow) { - setOverflow(listRef.current?.offsetWidth < listRef.current?.scrollWidth) - } else { - setOverflow(listRef.current?.offsetHeight < listRef.current?.scrollHeight) + if (listRef.current.offsetWidth < listRef.current.scrollWidth) { + toggleRowButtonVisibility(listRef.current) + } else { + setOverflowStart(false) + setOverflowEnd(false) + } + } + + // if there is overflow for columns + if (isCol) { + if (listRef.current.offsetHeight < listRef.current.scrollHeight) { + toggleColButtonVisibility(listRef.current) + } else { + setOverflowStart(false) + setOverflowEnd(false) + } } - }, [dimensions, disableScroll]) + } + + useLayoutEffect(() => { + calculateScroll() + }, [dimensions, layout]) return ( { role="tablist" className={className} aria-orientation={isCol ? 'vertical' : 'horizontal'}> - {overflow && ( -
- +
)}
isRow ? toggleRowButtonVisibility(e.currentTarget) : toggleColButtonVisibility(e.currentTarget)} className={classNameInner} ref={listRef}>
@@ -206,13 +248,16 @@ export const TabList = (props: TabListProps) => { )}
- {overflow && ( -
- +
)} diff --git a/packages/core/src/task/task.css b/packages/core/src/task/task.css index c24baa26..95215bca 100644 --- a/packages/core/src/task/task.css +++ b/packages/core/src/task/task.css @@ -3,7 +3,7 @@ :root { --f-task-card-background: var(--f-color-surface); - --f-task-card-border: 0.1rem solid var(--f-color-border); + --f-task-card-border: 1px solid var(--f-color-border); --f-task-card-radius: var(--f-radius); --f-task-card-spacing-bottom: 0.25rem; --f-task-card-padding: 0.75rem; @@ -97,7 +97,7 @@ } .f-task-card .f-avatar { - border: 0.1rem solid var(--f-color-surface); + border: 1px solid var(--f-color-surface); } /* list item */ @@ -116,7 +116,7 @@ .f-task-list-item { background: var(--f-task-li-background); - border-top: 0.1rem solid var(--f-color-border); + border-top: 1px solid var(--f-color-border); border-radius: var(--f-task-li-radius); position: relative; width: 100%; @@ -156,7 +156,7 @@ } .f-task-list-item .f-avatar { - border: 0.1rem solid var(--f-color-surface); + border: 1px solid var(--f-color-surface); } .f-task-list-item__title { @@ -239,7 +239,7 @@ } .f-task-menu-button { - padding: 0.1rem; + padding: 0.15rem; display: none; position: absolute; top: var(--f-task-menu-y); diff --git a/packages/core/src/text/text.css b/packages/core/src/text/text.css index 149118ba..ede5ebe8 100644 --- a/packages/core/src/text/text.css +++ b/packages/core/src/text/text.css @@ -108,20 +108,35 @@ legend.f-text { .f-text.xs { font-size: var(--f-font-size-xs); + line-height: var(--f-font-size-xs); } .f-text.sm { font-size: var(--f-font-size-sm); + line-height: var(--f-font-size-sm); } .f-text.md { font-size: var(--f-font-size-md); + line-height: var(--f-font-size-md); } .f-text.lg { font-size: var(--f-font-size-lg); + line-height: var(--f-font-size-lg); } .f-text.xl { font-size: var(--f-font-size-xl); + line-height: var(--f-font-size-xl); +} + +/* default line height */ + +p.f-text.xs, +p.f-text.sm, +p.f-text.md, +p.f-text.lg, +p.f-text.xl { + line-height: default; } diff --git a/packages/core/src/textarea/textarea.css b/packages/core/src/textarea/textarea.css index 758ab367..9b2cfc82 100644 --- a/packages/core/src/textarea/textarea.css +++ b/packages/core/src/textarea/textarea.css @@ -1,7 +1,7 @@ :root { --f-textarea-background-color: var(--f-color-surface); --f-textarea-border-color: var(--f-color-border); - --f-textarea-border-width: 0.1rem; + --f-textarea-border-width: 1px; --f-textarea-border-color-active: var(--f-color-border-strong); --f-textarea-color: var(--f-color-text-weak); --f-textarea-color-placeholder: var(--f-color-text-weakest); diff --git a/packages/core/src/textarea/textarea.tsx b/packages/core/src/textarea/textarea.tsx index accdbcb6..24f2b671 100644 --- a/packages/core/src/textarea/textarea.tsx +++ b/packages/core/src/textarea/textarea.tsx @@ -34,7 +34,7 @@ export const Textarea = forwardRef((props: TextareaProps, ref) => { } } - const onFocus = () => textareaRef.current?.select() + const onFocus = () => selectOnFocus ? textareaRef.current?.select() : null useEffect(() => { if (!textareaRef.current) return diff --git a/packages/core/src/timeline/timeline.css b/packages/core/src/timeline/timeline.css index 39095c73..2ec05873 100644 --- a/packages/core/src/timeline/timeline.css +++ b/packages/core/src/timeline/timeline.css @@ -6,14 +6,15 @@ --f-timeline-item-marker-line-spacing: 0.5rem; --f-timeline-item-marker-width: 1.5rem; --f-timeline-item-marker-spacing: var(--f-size-2); - --f-timeline-item-spacing: var(--f-size-3); + --f-timeline-item-margin: var(--f-size-3); + --f-timeline-item-padding: var(--f-size-4); --f-timeline-item-marker-top: 1px; } .f-timeline {} .f-timeline > .f-timeline-item + .f-timeline-item { - margin-top: var(--f-timeline-item-spacing); + margin-top: var(--f-timeline-item-margin); } .f-timeline-item { @@ -35,6 +36,7 @@ overflow: hidden; width: var(--f-timeline-item-marker-width); top: var(--f-timeline-item-marker-top); /* tiny hack to get it lined up with container start */ + padding-bottom: var(--f-timeline-item-padding); } .f-timeline-item__marker > * { diff --git a/packages/core/src/timeline/timeline.stories.tsx b/packages/core/src/timeline/timeline.stories.tsx index b15207ac..388861f5 100644 --- a/packages/core/src/timeline/timeline.stories.tsx +++ b/packages/core/src/timeline/timeline.stories.tsx @@ -18,7 +18,8 @@ export const Usage = () => ( Checked in at the hotel. - 6m ago @@ -27,6 +28,7 @@ export const Usage = () => ( Departed JFK airport via Uber. 56m ago @@ -37,6 +39,7 @@ export const Usage = () => ( Passed through security checkpoint. Entered airport facility. 3h ago @@ -45,6 +48,7 @@ export const Usage = () => ( Caught an Uber bound for the airport. 6h ago @@ -72,6 +76,7 @@ export const CustomMarkers = () => ( }> Checked in at the hotel. 6m ago @@ -87,6 +92,7 @@ export const CustomMarkers = () => ( }> Departed JFK airport via Uber. 56m ago @@ -97,6 +103,7 @@ export const CustomMarkers = () => ( Passed through security checkpoint. Entered airport facility. 3h ago @@ -105,6 +112,7 @@ export const CustomMarkers = () => ( }> Caught an Uber bound for the airport. 6h ago diff --git a/packages/core/src/upload/upload.css b/packages/core/src/upload/upload.css index 8bc570d9..600add38 100644 --- a/packages/core/src/upload/upload.css +++ b/packages/core/src/upload/upload.css @@ -1,8 +1,8 @@ :root { --f-upload-border-radius: var(--f-radius); - --f-upload-border: 0.2rem solid var(--f-color-border); - --f-upload-border-hover: 0.2rem solid var(--f-color-border-strong); - --f-upload-border-active: 0.2rem dashed var(--f-color-accent); + --f-upload-border: 1px solid var(--f-color-border); + --f-upload-border-hover: 1px solid var(--f-color-border-strong); + --f-upload-border-active: 1px dashed var(--f-color-accent); --f-upload-background: var(--f-color-surface-strong); --f-upload-color: var(--f-color-text); --f-upload-color-sub: var(--f-color-text-weaker); diff --git a/packages/design/package.json b/packages/design/package.json index 67c351c7..d0350d6a 100644 --- a/packages/design/package.json +++ b/packages/design/package.json @@ -1,7 +1,7 @@ { "name": "@fold-dev/design", "title": "Design Tokens", - "version": "0.4.0", + "version": "0.5.0", "description": "The UI library for product teams.", "main": "", "module": "", diff --git a/packages/design/tokens/font.json b/packages/design/tokens/font.json index f62f06d7..be17e0ee 100644 --- a/packages/design/tokens/font.json +++ b/packages/design/tokens/font.json @@ -1,7 +1,7 @@ { "font": { - "heading": { "value": "-apple-system,system-ui,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif" }, - "body": { "value": "-apple-system,system-ui,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif" }, + "heading": { "value": "Inter,-apple-system,system-ui,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif" }, + "body": { "value": "Inter,-apple-system,system-ui,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif" }, "mono": { "value": "SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace" } } }