Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Searchbox overflowing when displaying long name #992 #995

Merged
merged 1 commit into from
Oct 23, 2024
Merged
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
1 change: 1 addition & 0 deletions browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This changelog covers all five packages, as they are (for now) updated as a whol

- [#981](https://github.com/atomicdata-dev/atomic-server/issues/981) Fix bug where the service worker would not update cache with updated code.
- [#989](https://github.com/atomicdata-dev/atomic-server/issues/989) Added an edit button to the resource selector inputs.
- [#992](https://github.com/atomicdata-dev/atomic-server/issues/992) Fix Searchbox overflowing when displaying long names.

### @tomic/cli

Expand Down
5 changes: 4 additions & 1 deletion browser/data-browser/src/components/Collapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ const GridCollapser = styled.div<GridCollapserProps>`
display: grid;
grid-template-rows: ${({ open }) => (open ? '1fr' : '0fr')};
grid-template-columns: 100%;
transition: grid-template-rows ${() => ANIMATION_DURATION()}ms ease-in-out;
transition:
grid-template-rows ${() => ANIMATION_DURATION()}ms ease-in-out,
// In some cases, a margin is added. This needs to animate as well.
margin-top ${() => ANIMATION_DURATION()}ms ease-in-out;

@media (prefers-reduced-motion) {
transition: unset;
Expand Down
27 changes: 15 additions & 12 deletions browser/data-browser/src/components/Containers.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import { styled } from 'styled-components';
import { css, styled } from 'styled-components';
import { LAYOUT_CONTAINER } from '../helpers/containers';

/** Centered column */
export const ContainerNarrow = styled.div`
width: min(100%, ${props => props.theme.containerWidth}rem);
const common = css`
margin: auto;
padding: ${props => props.theme.margin}rem;
// Extra space for the navbar below
padding: ${p => p.theme.size()};
container: ${LAYOUT_CONTAINER} / inline-size;
padding-bottom: 10rem;
`;

/** Centered column */
export const ContainerNarrow = styled.div`
width: min(100%, ${p => p.theme.containerWidth}rem);
${common}
`;

export const ContainerWide = styled.div`
width: min(100%, ${props => props.theme.containerWidthWide});
margin: auto;
padding: ${props => props.theme.margin}rem;
// Extra space for the navbar below
padding-bottom: 10rem;
width: min(100%, ${p => p.theme.containerWidthWide});
${common}
`;

/** Full-page wrapper */
export const ContainerFull = styled.div`
padding: ${props => props.theme.margin}rem;
container: ${LAYOUT_CONTAINER} / inline-size;
padding: ${p => p.theme.size()};
padding-bottom: 10rem;
`;
19 changes: 11 additions & 8 deletions browser/data-browser/src/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { useDialog } from './useDialog';
import { useControlLock } from '../../hooks/useControlLock';
import { useDialogGlobalContext } from './DialogGlobalContextProvider';
import { DIALOG_CONTENT_CONTAINER } from '../../helpers/containers';

export interface InternalDialogProps {
show: boolean;
Expand Down Expand Up @@ -216,16 +217,19 @@ const DialogContentSlot = styled(Slot)`
overflow-y: visible;
/* The main section should leave room for the footer */
max-height: calc(80vh - 8rem);
padding-bottom: ${({ theme }) => theme.margin}rem;
padding-bottom: ${p => p.theme.size()};
// Position the scrollbar against the side of the dialog without any spacing inbetween.
// This also fixes ugly horizontal shadow cutoff.
margin-inline: -${p => p.theme.margin}rem;
padding-inline: ${p => p.theme.margin}rem;
margin-inline: -${p => p.theme.size()};
padding-inline: ${p => p.theme.size()};

container: ${DIALOG_CONTENT_CONTAINER} / inline-size;
scrollbar-gutter: stable;
`;

const DialogActionsSlot = styled(Slot)`
display: flex;
gap: ${p => p.theme.margin}rem;
gap: ${p => p.theme.size()};
align-items: center;
justify-content: flex-end;
border-top: 1px solid ${props => props.theme.colors.bg2};
Expand All @@ -238,7 +242,7 @@ const StyledInnerDialog = styled.div`
grid-template-rows: 1fr auto auto;
gap: 1rem;
grid-template-areas: 'title close' 'content content' 'actions actions';
max-block-size: calc(100vh - ${p => p.theme.margin}rem * 2);
max-block-size: calc(100vh - ${p => p.theme.size()} * 2);
`;

const fadeInForground = keyframes`
Expand All @@ -264,18 +268,17 @@ const fadeInBackground = keyframes`
`;

const StyledDialog = styled.dialog<{ $width?: CSS.Property.Width }>`
--animation-speed: 500ms;
--dialog-width: min(90vw, ${p => p.$width ?? '60ch'});

${VAR_DIALOG_INNER_WIDTH}: calc(
var(--dialog-width) - 2 * ${p => p.theme.margin}rem
var(--dialog-width) - 2 * ${p => p.theme.size()}
);

box-sizing: border-box;
inset: 0px;
position: relative;
z-index: ${p => p.theme.zIndex.dialog};
padding: ${props => props.theme.margin}rem;
padding: ${p => p.theme.size()};
color: ${props => props.theme.colors.text};
background-color: ${props => props.theme.colors.bg};
border-radius: ${props => props.theme.radius};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function SelectedFileLayout({
}: PropsWithChildren<SelectedFileLayoutProps>): React.JSX.Element {
return (
<Wrapper>
<Row>
<Row center>
<Title>{title}</Title>
{!disabled && (
<IconButton title='clear' onClick={onClear}>
Expand All @@ -35,7 +35,8 @@ export function SelectedFileLayout({
}

const Title = styled.span`
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
`;

const Wrapper = styled.div`
Expand Down
5 changes: 5 additions & 0 deletions browser/data-browser/src/components/forms/InputStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ export const FieldStyled = styled.div`
margin-bottom: ${props => props.theme.size()};
border: none;
background-color: none;

// Removes default 1px margin on fieldset.
&:is(fieldset) {
margin-inline: 0;
}
`;

export const LabelWrapper = styled.div`
Expand Down
7 changes: 1 addition & 6 deletions browser/data-browser/src/components/forms/ResourceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,6 @@ export function ResourceForm({
<Button
title={'show / hide advanced form fields'}
clean
style={{
display: 'flex',
marginBottom: '1rem',
alignItems: 'center',
}}
onClick={() => setShowAdvanced(!showAdvanced)}
>
<Row as='strong' gap='0.4rem' center>
Expand Down Expand Up @@ -309,5 +304,5 @@ export function ResourceForm({
}

const StyledCollapse = styled(Collapse)`
max-width: 70ch;
margin-top: ${p => (p.open ? '1rem' : '0')};
`;
13 changes: 11 additions & 2 deletions browser/data-browser/src/components/forms/SearchBox/SearchBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
useRef,
useState,
} from 'react';
import { styled } from 'styled-components';
import { css, styled } from 'styled-components';
import { removeCachedSearchResults, useResource, useStore } from '@tomic/react';
import { DropdownPortalContext } from '../../Dropdown/dropdownContext';
import * as RadixPopover from '@radix-ui/react-popover';
Expand Down Expand Up @@ -163,6 +163,7 @@ export function SearchBox({
<TriggerButtonWrapper
disabled={!!disabled}
className={className}
open={open}
invalid={!!visualError}
>
{prefix}
Expand Down Expand Up @@ -259,10 +260,14 @@ const TriggerButton = styled.button<{ $empty: boolean }>`
const TriggerButtonWrapper = styled.div<{
invalid: boolean;
disabled: boolean;
open: boolean;
}>`
${SB_HIGHLIGHT.define(p =>
p.invalid ? p.theme.colors.alert : p.theme.colors.main,
)}

max-width: 100cqw;

display: flex;
position: relative;
border: 1px solid ${props => props.theme.colors.bg2};
Expand All @@ -284,7 +289,11 @@ const TriggerButtonWrapper = styled.div<{
&:focus-visible {
border-color: transparent;
box-shadow: 0 0 0 2px ${SB_HIGHLIGHT.var()};
z-index: 1000;
${p =>
!p.open &&
css`
z-index: 1000;
`}
}
`;

Expand Down
2 changes: 2 additions & 0 deletions browser/data-browser/src/helpers/containers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const MAIN_CONTAINER = 'main';
export const ALL_PROPS_CONTAINER = 'all-props';
export const CARD_CONTAINER = 'card';
export const LAYOUT_CONTAINER = 'layout-container';
export const DIALOG_CONTENT_CONTAINER = 'dialog-content';
14 changes: 6 additions & 8 deletions browser/data-browser/src/hooks/useFile.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { properties, Resource, useNumber, useString } from '@tomic/react';
import { Resource, server, useNumber, useString } from '@tomic/react';
import { useCallback } from 'react';

export function useFileInfo(resource: Resource) {
const [downloadUrl] = useString(resource, properties.file.downloadUrl);
const [mimeType] = useString(resource, properties.file.mimetype);

const [bytes] = useNumber(resource, properties.file.filesize);
const [downloadUrl] = useString(resource, server.properties.downloadUrl);
const [mimeType] = useString(resource, server.properties.mimetype);
const [bytes] = useNumber(resource, server.properties.filesize);

const downloadFile = useCallback(() => {
window.open(downloadUrl);
}, [downloadUrl]);

if (
downloadUrl === undefined ||
mimeType === undefined ||
bytes === undefined
!resource.loading &&
(downloadUrl === undefined || mimeType === undefined || bytes === undefined)
) {
throw new Error('File resource is missing properties');
}
Expand Down
3 changes: 3 additions & 0 deletions browser/data-browser/src/styling.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ export const GlobalStyle = createGlobalStyle`
line-height: 1.5em;
word-wrap: break-word;
overflow-wrap: anywhere;
// Prevents weird scrollbars appearing for a split second when opening a dialog
overflow: hidden;

margin: 0;
/** Pretty dark mode transition */
transition: background-color .2s ease, border-color .2s ease, color .2s ease;
Expand Down
36 changes: 22 additions & 14 deletions browser/react/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
Resource,
Datatype,
datatypeFromUrl,
urls,
truncateUrl,
JSONValue,
valToBoolean,
Expand All @@ -28,6 +27,8 @@ import {
proxyResource,
type Core,
ResourceEvents,
core,
server,
} from '@tomic/lib';
import { useDebouncedCallback } from './index.js';

Expand Down Expand Up @@ -216,6 +217,7 @@ export function useValue(
commitDebounce = 100,
handleValidationError,
} = opts;

const [val, set] = useState<JSONValue>(resource.get(propertyURL));
const [prevResourceReference, setPrevResourceReference] = useState(resource);

Expand Down Expand Up @@ -267,24 +269,30 @@ export function useValue(
[resource, handleValidationError, store, validate, saveResource],
);

useEffect(() => {
return resource.on(ResourceEvents.LocalChange, (prop, value) => {
if (prop === propertyURL) {
set(value);
}
});
}, [resource, propertyURL]);

// Update value when resource changes.
if (resource !== prevResourceReference) {
let localVal: JSONValue | undefined;

try {
set(resource.get(propertyURL));
localVal = resource.get(propertyURL);
set(localVal);
} catch (e) {
store.notifyError(e);
}

setPrevResourceReference(resource);
}

useEffect(() => {
return resource.on(ResourceEvents.LocalChange, (prop, value) => {
if (prop === propertyURL) {
set(value);
}
});
}, [resource, propertyURL]);
// We changed the value but we don't want to wait a whole react cycle to return the new value so we return the value here directly.
return [localVal, validateAndSet];
}

return [val, validateAndSet];
}
Expand Down Expand Up @@ -351,15 +359,15 @@ export function useTitle(
truncateLength = 40,
opts: useValueOptions = titleHookOpts,
): [string, SetValue<string>] {
const [name, setName] = useString(resource, urls.properties.name, opts);
const [name, setName] = useString(resource, core.properties.name, opts);
const [shortname, setShortname] = useString(
resource,
urls.properties.shortname,
core.properties.shortname,
opts,
);
const [filename, setFileName] = useString(
resource,
urls.properties.file.filename,
server.properties.filename,
opts,
);

Expand All @@ -379,7 +387,7 @@ export function useTitle(
return [filename, setFileName];
}

const subject = resource?.getSubject();
const subject = resource?.subject;

if (typeof subject === 'string' && subject.length > 0) {
return [truncateUrl(subject, truncateLength), setName];
Expand Down
Loading